mirror of
https://github.com/Luzifer/go-holidays.git
synced 2024-10-18 14:14:20 +00:00
103 lines
2.7 KiB
Go
103 lines
2.7 KiB
Go
package holidays
|
|
|
|
//go:generate go-bindata -pkg $GOPACKAGE -o holidays_data.go holidays/...
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"path"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
|
|
yaml "gopkg.in/yaml.v2"
|
|
)
|
|
|
|
var HolidayDataNotFoundError = errors.New("Holiday data not found for requested country-code")
|
|
|
|
// Holiday contains information about an holiday
|
|
type Holiday struct {
|
|
// Name contains the english representation of the holidays name
|
|
Name string
|
|
// LocalizedName contains a map of localizations of the name, key is a ISO 3166-2 country code without subdivision
|
|
LocalizedName map[string]string
|
|
// Date contains the date with time.Local zone
|
|
Date time.Time
|
|
}
|
|
|
|
type holidays []Holiday
|
|
|
|
func (h holidays) Len() int { return len(h) }
|
|
func (h holidays) Less(i, j int) bool { return h[i].Date.Before(h[j].Date) }
|
|
func (h holidays) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
|
|
|
// GetHolidays returns the holidays for the given ISO 3166-2 countryCode and year
|
|
func GetHolidays(countryCode string, year int) ([]Holiday, error) {
|
|
requiredFiles := []string{countryCode}
|
|
result := []Holiday{}
|
|
|
|
for len(requiredFiles) > 0 {
|
|
hdf, err := loadDataFile(requiredFiles[0])
|
|
if err != nil {
|
|
return result, err
|
|
}
|
|
|
|
requiredFiles = append(requiredFiles, hdf.Includes...)
|
|
|
|
easter := GregorianEasterSunday(year)
|
|
|
|
for _, h := range hdf.Holidays.Fixed {
|
|
result = append(result, Holiday{
|
|
Name: h.Name,
|
|
LocalizedName: h.LocalizedName,
|
|
Date: time.Date(year, time.Month(h.Month), h.Day, 0, 0, 0, 0, time.Local),
|
|
})
|
|
}
|
|
|
|
for _, h := range hdf.Holidays.EasterBased {
|
|
result = append(result, Holiday{
|
|
Name: h.Name,
|
|
LocalizedName: h.LocalizedName,
|
|
Date: easter.Add(time.Duration(h.Difference) * 24 * time.Hour),
|
|
})
|
|
}
|
|
|
|
requiredFiles = requiredFiles[1:]
|
|
}
|
|
|
|
sort.Sort(holidays(result))
|
|
|
|
return result, nil
|
|
}
|
|
|
|
type holidaysDataFileEntry struct {
|
|
Name string `yaml:"name"`
|
|
LocalizedName map[string]string `yaml:"localized"`
|
|
Month int `yaml:"month"`
|
|
Day int `yaml:"day"`
|
|
Difference int `yaml:"difference"`
|
|
}
|
|
|
|
type holidaysDataFile struct {
|
|
Includes []string `yaml:"includes"`
|
|
Holidays struct {
|
|
Fixed []holidaysDataFileEntry `yaml:"fixed"`
|
|
EasterBased []holidaysDataFileEntry `yaml:"easter_based"`
|
|
} `yaml:"holidays"`
|
|
}
|
|
|
|
func loadDataFile(countryCode string) (holidaysDataFile, error) {
|
|
r := holidaysDataFile{}
|
|
|
|
parts := strings.Split(countryCode, "-")
|
|
if len(parts) == 1 {
|
|
parts = append(parts, "_")
|
|
}
|
|
|
|
data, err := Asset(fmt.Sprintf(path.Join("holidays", parts[0], parts[1]) + ".yaml"))
|
|
if err != nil {
|
|
return r, HolidayDataNotFoundError
|
|
}
|
|
|
|
return r, yaml.Unmarshal(data, &r)
|
|
}
|