diff --git a/v2/jp/jp_holidays.go b/v2/jp/jp_holidays.go new file mode 100644 index 0000000..4131727 --- /dev/null +++ b/v2/jp/jp_holidays.go @@ -0,0 +1,354 @@ +// (c) Rick Arnold. Licensed under the BSD license (see LICENSE). + +// Package jp provides holiday definitions for Japan. +package jp + +import ( + "github.com/rickar/cal/v2" + "github.com/rickar/cal/v2/aa" + "math" + "time" +) + +var ( + // Standard Japan weekend substitution rules: Sundays move to Monday + weekendAlt = []cal.AltDay{ + {Day: time.Sunday, Offset: 1}, + } + + // NewYear represents New Year's Day on 1-Jan + NewYear = aa.NewYear.Clone(&cal.Holiday{Type: cal.ObservancePublic, Observed: weekendAlt}) + + // ComingOfAgeDay represents Coming of Age Day on the 2nd Monday in January + ComingOfAgeDay = &cal.Holiday{ + Name: "Coming of Age Day", + Type: cal.ObservancePublic, + Month: time.January, + Weekday: time.Monday, + Offset: 2, + Func: cal.CalcWeekdayOffset, + } + + // NationalFoundationDay represents National Foundation Day on 11-February + NationalFoundationDay = &cal.Holiday{ + Name: "National Foundation Day", + Type: cal.ObservancePublic, + Month: time.February, + Day: 11, + Observed: weekendAlt, + Func: cal.CalcDayOfMonth, + } + + // TheEmperorsBirthday represents The Emperor's Birthday on 23-February + TheEmperorsBirthday = &cal.Holiday{ + Name: "The Emperor's Birthday", + Type: cal.ObservancePublic, + Month: time.February, + Day: 23, + Observed: weekendAlt, + Func: func(h *cal.Holiday, year int) time.Time { + if year <= 2019 { + // Emperor Akihito abdicated in 2019. + holiday := *h + holiday.Month = time.December + holiday.Day = 23 + + return cal.CalcDayOfMonth(&holiday, year) + } + + return cal.CalcDayOfMonth(h, year) + }, + } + + // VernalEquinoxDay represents Vernal Equinox Day on Around 20-March + VernalEquinoxDay = &cal.Holiday{ + Name: "Vernal Equinox Day", + Type: cal.ObservancePublic, + Month: time.March, + Observed: weekendAlt, + Func: func(h *cal.Holiday, year int) time.Time { + holiday := h + holiday.Day = calcVernalEquinoxDate(year) + + return cal.CalcDayOfMonth(holiday, year) + }, + } + + // ShowaDay represents Showa Day on 29-April + ShowaDay = &cal.Holiday{ + Name: "Showa Day", + Type: cal.ObservancePublic, + Month: time.April, + Day: 29, + Observed: weekendAlt, + Func: cal.CalcDayOfMonth, + } + + // ConstitutionMemorialDay represents Constitution Memorial Day on 3-May + ConstitutionMemorialDay = &cal.Holiday{ + Name: "Constitution Memorial Day", + Type: cal.ObservancePublic, + Month: time.May, + Day: 3, + Observed: []cal.AltDay{ + {Day: time.Sunday, Offset: 3}, + }, + Func: cal.CalcDayOfMonth, + } + + // GreeneryDay represents Greenery Day on 4-May + GreeneryDay = &cal.Holiday{ + Name: "Greenery Day", + Type: cal.ObservancePublic, + Month: time.May, + Day: 4, + Observed: []cal.AltDay{ + {Day: time.Sunday, Offset: 2}, + }, + Func: cal.CalcDayOfMonth, + } + + // ChildrensDay represents Children's Day on 5-May + ChildrensDay = &cal.Holiday{ + Name: "Children's Day", + Type: cal.ObservancePublic, + Month: time.May, + Day: 5, + Observed: weekendAlt, + Func: cal.CalcDayOfMonth, + } + + // MarineDay represents Marine Day on the 3rd Monday in July + MarineDay = &cal.Holiday{ + Name: "Marine Day", + Type: cal.ObservancePublic, + Month: time.July, + Weekday: time.Monday, + Offset: 3, + Func: func(h *cal.Holiday, year int) time.Time { + if year == 2020 || year == 2021 { + // As special arrangement for the 2020 Summer Olympics, the 2020 and 2021 date for Marine Day was moved + holiday := *h + holiday.Weekday = time.Thursday + holiday.Offset = 4 + + return cal.CalcWeekdayOffset(&holiday, year) + } + + return cal.CalcWeekdayOffset(h, year) + }, + } + + // MountainDay represents Mountain Day on 11-August + MountainDay = &cal.Holiday{ + Name: "Mountain Day", + Type: cal.ObservancePublic, + Month: time.August, + Day: 11, + Observed: weekendAlt, + Func: cal.CalcDayOfMonth, + StartYear: 2016, + } + + // RespectForTheAgedDay represents Respect for the Aged Day on the 3rd Monday in September + RespectForTheAgedDay = &cal.Holiday{ + Name: "Respect for the Aged Day", + Type: cal.ObservancePublic, + Month: time.September, + Weekday: time.Monday, + Offset: 3, + Func: cal.CalcWeekdayOffset, + } + + // AutumnalEquinoxDay represents Autumnal Equinox Day on Around 23-September + AutumnalEquinoxDay = &cal.Holiday{ + Name: "Autumnal Equinox Day", + Type: cal.ObservancePublic, + Month: time.September, + Observed: weekendAlt, + Func: func(h *cal.Holiday, year int) time.Time { + holiday := *h + holiday.Day = calcAutumnalEquinoxDate(year) + + return cal.CalcDayOfMonth(&holiday, year) + }, + } + + // SportsDay represents Sports Day on the 2nd Monday in October + SportsDay = &cal.Holiday{ + Name: "Sports Day", + Type: cal.ObservancePublic, + Month: time.October, + Weekday: time.Monday, + Offset: 2, + Func: func(h *cal.Holiday, year int) time.Time { + if year == 2020 || year == 2021 { + // As special arrangement for the 2020 Summer Olympics, the 2020 and 2021 date for Sports Day was moved + holiday := *h + holiday.Month = time.July + holiday.Weekday = time.Friday + holiday.Offset = 4 + + return cal.CalcWeekdayOffset(&holiday, year) + } + + return cal.CalcWeekdayOffset(h, year) + }, + } + + // CultureDay represents Culture Day on 3-November + CultureDay = &cal.Holiday{ + Name: "Culture Day", + Type: cal.ObservancePublic, + Month: time.November, + Day: 3, + Observed: weekendAlt, + Func: cal.CalcDayOfMonth, + } + + // LaborThanksgivingDay represents Labor Thanksgiving Day on 23-November + LaborThanksgivingDay = &cal.Holiday{ + Name: "Labor Thanksgiving Day", + Type: cal.ObservancePublic, + Month: time.November, + Day: 23, + Observed: weekendAlt, + Func: cal.CalcDayOfMonth, + } + + // NationalHolidayBetweenRespectForTheAgedDayAndAutumnalEquinoxDay represents National holiday between Respect for the Aged Day and Autumnal Equinox Day in September + NationalHolidayBetweenRespectForTheAgedDayAndAutumnalEquinoxDay = &cal.Holiday{ + Name: "National holiday between Respect for the Aged Day and Autumnal Equinox Day", + Type: cal.ObservancePublic, + Month: time.September, + Func: func(h *cal.Holiday, year int) time.Time { + switch year { + // only dates in September 2009 - 2032 are supported + case 2009: + return time.Date(year, h.Month, 22, 0, 0, 0, 0, cal.DefaultLoc) + case 2015: + return time.Date(year, h.Month, 22, 0, 0, 0, 0, cal.DefaultLoc) + case 2026: + return time.Date(year, h.Month, 22, 0, 0, 0, 0, cal.DefaultLoc) + case 2032: + return time.Date(year, h.Month, 21, 0, 0, 0, 0, cal.DefaultLoc) + default: + return time.Time{} + } + }, + } + + // NationalHolidayBetweenShowaDayAndNewEmperorEnthronementDay represents + // National Holiday Between Showa Day And New Emperor Enthronement Day on 30-April 2019 + NationalHolidayBetweenShowaDayAndNewEmperorEnthronementDay = &cal.Holiday{ + Name: "National Holiday Between Showa Day And New Emperor Enthronement Day", + Type: cal.ObservancePublic, + Month: time.April, + Day: 30, + Func: cal.CalcDayOfMonth, + StartYear: 2019, + EndYear: 2019, + } + + // TheNewEmperorEnthronementDay represents The New Emperor Enthronement Day on 1-May 2019 + TheNewEmperorEnthronementDay = &cal.Holiday{ + Name: "New Emperor Enthronement Day", + Type: cal.ObservancePublic, + Month: time.May, + Day: 1, + Func: cal.CalcDayOfMonth, + StartYear: 2019, + EndYear: 2019, + } + + // NationalHolidayBetweenTheNewEmperorEnthronementDayAndConstitutionMemorialDay represents + // National holiday between The New Emperor Enthronement Day and Constitution Memorial Day on 2-May 2019 + NationalHolidayBetweenTheNewEmperorEnthronementDayAndConstitutionMemorialDay = &cal.Holiday{ + Name: "National holiday between New Emperor Enthronement Day and Constitution Memorial Day", + Type: cal.ObservancePublic, + Month: time.May, + Day: 2, + Func: cal.CalcDayOfMonth, + StartYear: 2019, + EndYear: 2019, + } + + // TheNewEmperorEnthronementCeremony represents The New Emperor Enthronement Day on 22-October 2019 + TheNewEmperorEnthronementCeremony = &cal.Holiday{ + Name: "The New Emperor Enthronement Ceremony", + Type: cal.ObservancePublic, + Month: time.October, + Day: 22, + Func: cal.CalcDayOfMonth, + StartYear: 2019, + EndYear: 2019, + } + + exceptionalNationalHolidays = []*cal.Holiday{ + NationalHolidayBetweenRespectForTheAgedDayAndAutumnalEquinoxDay, + NationalHolidayBetweenShowaDayAndNewEmperorEnthronementDay, + TheNewEmperorEnthronementDay, + NationalHolidayBetweenTheNewEmperorEnthronementDayAndConstitutionMemorialDay, + TheNewEmperorEnthronementCeremony, + } + + Holidays = append( + []*cal.Holiday{ + NewYear, + ComingOfAgeDay, + NationalFoundationDay, + TheEmperorsBirthday, + VernalEquinoxDay, + ShowaDay, + ConstitutionMemorialDay, + GreeneryDay, + ChildrensDay, + MarineDay, + MountainDay, + RespectForTheAgedDay, + AutumnalEquinoxDay, + SportsDay, + CultureDay, + LaborThanksgivingDay, + }, + exceptionalNationalHolidays..., + ) +) + +func calcVernalEquinoxDate(year int) int { + val := calcEquinoxBase(year) + + switch { + case 1851 <= year && year <= 1899: + val += 19.8277 + case 1900 <= year && year <= 1979: + val += 20.8357 + case 1980 <= year && year <= 2099: + val += 20.8431 + case 2100 <= year && year <= 2150: + val += 21.8510 + } + + return int(math.Floor(val)) +} + +func calcAutumnalEquinoxDate(year int) int { + val := calcEquinoxBase(year) + + switch { + case 1851 <= year && year <= 1899: + val += 22.2588 + case 1900 <= year && year <= 1979: + val += 23.2588 + case 1980 <= year && year <= 2099: + val += 23.2488 + case 2100 <= year && year <= 2150: + val += 24.2488 + } + + return int(math.Floor(val)) +} + +func calcEquinoxBase(year int) float64 { + return 0.242194*float64(year-1980) - math.Floor(float64(year-1980)/4.0) +} diff --git a/v2/jp/jp_holidays_test.go b/v2/jp/jp_holidays_test.go new file mode 100644 index 0000000..689bee8 --- /dev/null +++ b/v2/jp/jp_holidays_test.go @@ -0,0 +1,223 @@ +// (c) Rick Arnold. Licensed under the BSD license (see LICENSE). + +package jp + +import ( + "github.com/rickar/cal/v2" + "testing" + "time" +) + +func d(y, m, d int) time.Time { + return time.Date(y, time.Month(m), d, 0, 0, 0, 0, cal.DefaultLoc) +} + +func TestHolidays(t *testing.T) { + tests := []struct { + h *cal.Holiday + y int + wantAct time.Time + wantObs time.Time + }{ + {NewYear, 2015, d(2015, 1, 1), d(2015, 1, 1)}, + {NewYear, 2016, d(2016, 1, 1), d(2016, 1, 1)}, + {NewYear, 2017, d(2017, 1, 1), d(2017, 1, 2)}, + {NewYear, 2018, d(2018, 1, 1), d(2018, 1, 1)}, + {NewYear, 2019, d(2019, 1, 1), d(2019, 1, 1)}, + {NewYear, 2020, d(2020, 1, 1), d(2020, 1, 1)}, + {NewYear, 2021, d(2021, 1, 1), d(2021, 1, 1)}, + {NewYear, 2022, d(2022, 1, 1), d(2022, 1, 1)}, + + {ComingOfAgeDay, 2015, d(2015, 1, 12), d(2015, 1, 12)}, + {ComingOfAgeDay, 2016, d(2016, 1, 11), d(2016, 1, 11)}, + {ComingOfAgeDay, 2017, d(2017, 1, 9), d(2017, 1, 9)}, + {ComingOfAgeDay, 2018, d(2018, 1, 8), d(2018, 1, 8)}, + {ComingOfAgeDay, 2019, d(2019, 1, 14), d(2019, 1, 14)}, + {ComingOfAgeDay, 2020, d(2020, 1, 13), d(2020, 1, 13)}, + {ComingOfAgeDay, 2021, d(2021, 1, 11), d(2021, 1, 11)}, + {ComingOfAgeDay, 2022, d(2022, 1, 10), d(2022, 1, 10)}, + + {NationalFoundationDay, 2015, d(2015, 2, 11), d(2015, 2, 11)}, + {NationalFoundationDay, 2016, d(2016, 2, 11), d(2016, 2, 11)}, + {NationalFoundationDay, 2017, d(2017, 2, 11), d(2017, 2, 11)}, + {NationalFoundationDay, 2018, d(2018, 2, 11), d(2018, 2, 12)}, + {NationalFoundationDay, 2019, d(2019, 2, 11), d(2019, 2, 11)}, + {NationalFoundationDay, 2020, d(2020, 2, 11), d(2020, 2, 11)}, + {NationalFoundationDay, 2021, d(2021, 2, 11), d(2021, 2, 11)}, + {NationalFoundationDay, 2022, d(2022, 2, 11), d(2022, 2, 11)}, + + {TheEmperorsBirthday, 2015, d(2015, 12, 23), d(2015, 12, 23)}, + {TheEmperorsBirthday, 2016, d(2016, 12, 23), d(2016, 12, 23)}, + {TheEmperorsBirthday, 2017, d(2017, 12, 23), d(2017, 12, 23)}, + {TheEmperorsBirthday, 2018, d(2018, 12, 23), d(2018, 12, 24)}, + {TheEmperorsBirthday, 2019, d(2019, 12, 23), d(2019, 12, 23)}, + {TheEmperorsBirthday, 2020, d(2020, 2, 23), d(2020, 2, 24)}, + {TheEmperorsBirthday, 2021, d(2021, 2, 23), d(2021, 2, 23)}, + {TheEmperorsBirthday, 2022, d(2022, 2, 23), d(2022, 2, 23)}, + + {VernalEquinoxDay, 1851, d(1851, 3, 21), d(1851, 3, 21)}, + {VernalEquinoxDay, 1899, d(1899, 3, 21), d(1899, 3, 21)}, + {VernalEquinoxDay, 1900, d(1900, 3, 21), d(1900, 3, 21)}, + {VernalEquinoxDay, 1979, d(1979, 3, 21), d(1979, 3, 21)}, + {VernalEquinoxDay, 1980, d(1980, 3, 20), d(1980, 3, 20)}, + {VernalEquinoxDay, 2015, d(2015, 3, 21), d(2015, 3, 21)}, + {VernalEquinoxDay, 2016, d(2016, 3, 20), d(2016, 3, 21)}, + {VernalEquinoxDay, 2017, d(2017, 3, 20), d(2017, 3, 20)}, + {VernalEquinoxDay, 2018, d(2018, 3, 21), d(2018, 3, 21)}, + {VernalEquinoxDay, 2019, d(2019, 3, 21), d(2019, 3, 21)}, + {VernalEquinoxDay, 2020, d(2020, 3, 20), d(2020, 3, 20)}, + {VernalEquinoxDay, 2021, d(2021, 3, 20), d(2021, 3, 20)}, + {VernalEquinoxDay, 2022, d(2022, 3, 21), d(2022, 3, 21)}, + {VernalEquinoxDay, 2023, d(2023, 3, 21), d(2023, 3, 21)}, + {VernalEquinoxDay, 2024, d(2024, 3, 20), d(2024, 3, 20)}, + {VernalEquinoxDay, 2025, d(2025, 3, 20), d(2025, 3, 20)}, + {VernalEquinoxDay, 2026, d(2026, 3, 20), d(2026, 3, 20)}, + {VernalEquinoxDay, 2027, d(2027, 3, 21), d(2027, 3, 22)}, + {VernalEquinoxDay, 2028, d(2028, 3, 20), d(2028, 3, 20)}, + {VernalEquinoxDay, 2029, d(2029, 3, 20), d(2029, 3, 20)}, + {VernalEquinoxDay, 2030, d(2030, 3, 20), d(2030, 3, 20)}, + {VernalEquinoxDay, 2099, d(2099, 3, 20), d(2099, 3, 20)}, + {VernalEquinoxDay, 2100, d(2100, 3, 20), d(2100, 3, 20)}, + {VernalEquinoxDay, 2150, d(2150, 3, 21), d(2150, 3, 21)}, + + {ShowaDay, 2015, d(2015, 4, 29), d(2015, 4, 29)}, + {ShowaDay, 2016, d(2016, 4, 29), d(2016, 4, 29)}, + {ShowaDay, 2017, d(2017, 4, 29), d(2017, 4, 29)}, + {ShowaDay, 2018, d(2018, 4, 29), d(2018, 4, 30)}, + {ShowaDay, 2019, d(2019, 4, 29), d(2019, 4, 29)}, + {ShowaDay, 2020, d(2020, 4, 29), d(2020, 4, 29)}, + {ShowaDay, 2021, d(2021, 4, 29), d(2021, 4, 29)}, + {ShowaDay, 2022, d(2022, 4, 29), d(2022, 4, 29)}, + + {ConstitutionMemorialDay, 2015, d(2015, 5, 3), d(2015, 5, 6)}, + {ConstitutionMemorialDay, 2016, d(2016, 5, 3), d(2016, 5, 3)}, + {ConstitutionMemorialDay, 2017, d(2017, 5, 3), d(2017, 5, 3)}, + {ConstitutionMemorialDay, 2018, d(2018, 5, 3), d(2018, 5, 3)}, + {ConstitutionMemorialDay, 2019, d(2019, 5, 3), d(2019, 5, 3)}, + {ConstitutionMemorialDay, 2020, d(2020, 5, 3), d(2020, 5, 6)}, + {ConstitutionMemorialDay, 2021, d(2021, 5, 3), d(2021, 5, 3)}, + {ConstitutionMemorialDay, 2022, d(2022, 5, 3), d(2022, 5, 3)}, + + {GreeneryDay, 2014, d(2014, 5, 4), d(2014, 5, 6)}, + {GreeneryDay, 2015, d(2015, 5, 4), d(2015, 5, 4)}, + {GreeneryDay, 2016, d(2016, 5, 4), d(2016, 5, 4)}, + {GreeneryDay, 2017, d(2017, 5, 4), d(2017, 5, 4)}, + {GreeneryDay, 2018, d(2018, 5, 4), d(2018, 5, 4)}, + {GreeneryDay, 2019, d(2019, 5, 4), d(2019, 5, 4)}, + {GreeneryDay, 2020, d(2020, 5, 4), d(2020, 5, 4)}, + {GreeneryDay, 2021, d(2021, 5, 4), d(2021, 5, 4)}, + {GreeneryDay, 2022, d(2022, 5, 4), d(2022, 5, 4)}, + + {ChildrensDay, 2015, d(2015, 5, 5), d(2015, 5, 5)}, + {ChildrensDay, 2016, d(2016, 5, 5), d(2016, 5, 5)}, + {ChildrensDay, 2017, d(2017, 5, 5), d(2017, 5, 5)}, + {ChildrensDay, 2018, d(2018, 5, 5), d(2018, 5, 5)}, + {ChildrensDay, 2019, d(2019, 5, 5), d(2019, 5, 6)}, + {ChildrensDay, 2020, d(2020, 5, 5), d(2020, 5, 5)}, + {ChildrensDay, 2021, d(2021, 5, 5), d(2021, 5, 5)}, + {ChildrensDay, 2022, d(2022, 5, 5), d(2022, 5, 5)}, + + {MarineDay, 2015, d(2015, 7, 20), d(2015, 7, 20)}, + {MarineDay, 2016, d(2016, 7, 18), d(2016, 7, 18)}, + {MarineDay, 2017, d(2017, 7, 17), d(2017, 7, 17)}, + {MarineDay, 2018, d(2018, 7, 16), d(2018, 7, 16)}, + {MarineDay, 2019, d(2019, 7, 15), d(2019, 7, 15)}, + {MarineDay, 2020, d(2020, 7, 23), d(2020, 7, 23)}, + {MarineDay, 2021, d(2021, 7, 22), d(2021, 7, 22)}, + {MarineDay, 2022, d(2022, 7, 18), d(2022, 7, 18)}, + + {MountainDay, 2016, d(2016, 8, 11), d(2016, 8, 11)}, + {MountainDay, 2017, d(2017, 8, 11), d(2017, 8, 11)}, + {MountainDay, 2018, d(2018, 8, 11), d(2018, 8, 11)}, + {MountainDay, 2019, d(2019, 8, 11), d(2019, 8, 12)}, + {MountainDay, 2020, d(2020, 8, 11), d(2020, 8, 11)}, + {MountainDay, 2021, d(2021, 8, 11), d(2021, 8, 11)}, + {MountainDay, 2022, d(2022, 8, 11), d(2022, 8, 11)}, + + {RespectForTheAgedDay, 2015, d(2015, 9, 21), d(2015, 9, 21)}, + {RespectForTheAgedDay, 2016, d(2016, 9, 19), d(2016, 9, 19)}, + {RespectForTheAgedDay, 2017, d(2017, 9, 18), d(2017, 9, 18)}, + {RespectForTheAgedDay, 2018, d(2018, 9, 17), d(2018, 9, 17)}, + {RespectForTheAgedDay, 2019, d(2019, 9, 16), d(2019, 9, 16)}, + {RespectForTheAgedDay, 2020, d(2020, 9, 21), d(2020, 9, 21)}, + {RespectForTheAgedDay, 2021, d(2021, 9, 20), d(2021, 9, 20)}, + {RespectForTheAgedDay, 2022, d(2022, 9, 19), d(2022, 9, 19)}, + + {AutumnalEquinoxDay, 1851, d(1851, 9, 24), d(1851, 9, 24)}, + {AutumnalEquinoxDay, 1899, d(1899, 9, 23), d(1899, 9, 23)}, + {AutumnalEquinoxDay, 1900, d(1900, 9, 23), d(1900, 9, 24)}, + {AutumnalEquinoxDay, 1979, d(1979, 9, 24), d(1979, 9, 24)}, + {AutumnalEquinoxDay, 1980, d(1980, 9, 23), d(1980, 9, 23)}, + {AutumnalEquinoxDay, 2015, d(2015, 9, 23), d(2015, 9, 23)}, + {AutumnalEquinoxDay, 2016, d(2016, 9, 22), d(2016, 9, 22)}, + {AutumnalEquinoxDay, 2017, d(2017, 9, 23), d(2017, 9, 23)}, + {AutumnalEquinoxDay, 2018, d(2018, 9, 23), d(2018, 9, 24)}, + {AutumnalEquinoxDay, 2019, d(2019, 9, 23), d(2019, 9, 23)}, + {AutumnalEquinoxDay, 2020, d(2020, 9, 22), d(2020, 9, 22)}, + {AutumnalEquinoxDay, 2021, d(2021, 9, 23), d(2021, 9, 23)}, + {AutumnalEquinoxDay, 2022, d(2022, 9, 23), d(2022, 9, 23)}, + {AutumnalEquinoxDay, 2023, d(2023, 9, 23), d(2023, 9, 23)}, + {AutumnalEquinoxDay, 2024, d(2024, 9, 22), d(2024, 9, 23)}, + {AutumnalEquinoxDay, 2025, d(2025, 9, 23), d(2025, 9, 23)}, + {AutumnalEquinoxDay, 2026, d(2026, 9, 23), d(2026, 9, 23)}, + {AutumnalEquinoxDay, 2027, d(2027, 9, 23), d(2027, 9, 23)}, + {AutumnalEquinoxDay, 2028, d(2028, 9, 22), d(2028, 9, 22)}, + {AutumnalEquinoxDay, 2029, d(2029, 9, 23), d(2029, 9, 24)}, + {AutumnalEquinoxDay, 2030, d(2030, 9, 23), d(2030, 9, 23)}, + {AutumnalEquinoxDay, 2099, d(2099, 9, 23), d(2099, 9, 23)}, + {AutumnalEquinoxDay, 2100, d(2100, 9, 23), d(2100, 9, 23)}, + {AutumnalEquinoxDay, 2150, d(2150, 9, 23), d(2150, 9, 23)}, + + {SportsDay, 2015, d(2015, 10, 12), d(2015, 10, 12)}, + {SportsDay, 2016, d(2016, 10, 10), d(2016, 10, 10)}, + {SportsDay, 2017, d(2017, 10, 9), d(2017, 10, 9)}, + {SportsDay, 2018, d(2018, 10, 8), d(2018, 10, 8)}, + {SportsDay, 2019, d(2019, 10, 14), d(2019, 10, 14)}, + {SportsDay, 2020, d(2020, 7, 24), d(2020, 7, 24)}, + {SportsDay, 2021, d(2021, 7, 23), d(2021, 7, 23)}, + {SportsDay, 2022, d(2022, 10, 10), d(2022, 10, 10)}, + + {CultureDay, 2015, d(2015, 11, 3), d(2015, 11, 3)}, + {CultureDay, 2016, d(2016, 11, 3), d(2016, 11, 3)}, + {CultureDay, 2017, d(2017, 11, 3), d(2017, 11, 3)}, + {CultureDay, 2018, d(2018, 11, 3), d(2018, 11, 3)}, + {CultureDay, 2019, d(2019, 11, 3), d(2019, 11, 4)}, + {CultureDay, 2020, d(2020, 11, 3), d(2020, 11, 3)}, + {CultureDay, 2021, d(2021, 11, 3), d(2021, 11, 3)}, + {CultureDay, 2022, d(2022, 11, 3), d(2022, 11, 3)}, + + {LaborThanksgivingDay, 2014, d(2014, 11, 23), d(2014, 11, 24)}, + {LaborThanksgivingDay, 2015, d(2015, 11, 23), d(2015, 11, 23)}, + {LaborThanksgivingDay, 2016, d(2016, 11, 23), d(2016, 11, 23)}, + {LaborThanksgivingDay, 2017, d(2017, 11, 23), d(2017, 11, 23)}, + {LaborThanksgivingDay, 2018, d(2018, 11, 23), d(2018, 11, 23)}, + {LaborThanksgivingDay, 2019, d(2019, 11, 23), d(2019, 11, 23)}, + {LaborThanksgivingDay, 2020, d(2020, 11, 23), d(2020, 11, 23)}, + {LaborThanksgivingDay, 2021, d(2021, 11, 23), d(2021, 11, 23)}, + {LaborThanksgivingDay, 2022, d(2022, 11, 23), d(2022, 11, 23)}, + + {NationalHolidayBetweenRespectForTheAgedDayAndAutumnalEquinoxDay, 2009, d(2009, 9, 22), d(2009, 9, 22)}, + {NationalHolidayBetweenRespectForTheAgedDayAndAutumnalEquinoxDay, 2015, d(2015, 9, 22), d(2015, 9, 22)}, + {NationalHolidayBetweenRespectForTheAgedDayAndAutumnalEquinoxDay, 2026, d(2026, 9, 22), d(2026, 9, 22)}, + {NationalHolidayBetweenRespectForTheAgedDayAndAutumnalEquinoxDay, 2022, time.Time{}, time.Time{}}, + {NationalHolidayBetweenRespectForTheAgedDayAndAutumnalEquinoxDay, 2032, d(2032, 9, 21), d(2032, 9, 21)}, + + {NationalHolidayBetweenShowaDayAndNewEmperorEnthronementDay, 2019, d(2019, 4, 30), d(2019, 4, 30)}, + + {TheNewEmperorEnthronementDay, 2019, d(2019, 5, 1), d(2019, 5, 1)}, + + {NationalHolidayBetweenTheNewEmperorEnthronementDayAndConstitutionMemorialDay, 2019, d(2019, 5, 2), d(2019, 5, 2)}, + + {TheNewEmperorEnthronementCeremony, 2019, d(2019, 10, 22), d(2019, 10, 22)}, + } + + for _, test := range tests { + gotAct, gotObs := test.h.Calc(test.y) + if !gotAct.Equal(test.wantAct) { + t.Errorf("%s %d: got actual: %s, want: %s", test.h.Name, test.y, gotAct.String(), test.wantAct.String()) + } + if !gotObs.Equal(test.wantObs) { + t.Errorf("%s %d: got observed: %s, want: %s", test.h.Name, test.y, gotObs.String(), test.wantObs.String()) + } + } +}