// 日本祝日计算函数。返回 YYYY-MM-DD → 节假日名称的映射。 // weekday(date) 的周日为 0;date(year, month, day) 与 add_days(date, n) 生成日期。 // 规则适用 1955–2099 年;未公布年份的春秋分日为近似计算。 fn monday(year, month, nth) { let first = date(year, month, 1); 1 + (8 - weekday(first)) % 7 + 7 * (nth - 1) } fn japanese_holidays(year) { let h = #{}; if year < 1955 || year > 2099 { return h; } h[date(year, 1, 1)] = "元日"; h[date(year, 1, if year >= 2000 { monday(year, 1, 2) } else { 15 })] = "成人の日"; if year >= 1967 { h[date(year, 2, 11)] = "建国記念の日"; } if year >= 2020 { h[date(year, 2, 23)] = "天皇誕生日"; } if year >= 1989 && year <= 2018 { h[date(year, 12, 23)] = "天皇誕生日"; } h[date(year, 4, 29)] = if year >= 2007 { "昭和の日" } else if year >= 1989 { "みどりの日" } else { "天皇誕生日" }; // 春分・秋分近似式。官报公布前的将来日期仅为推算。 let spring_base = if year < 1980 { 20.8357 } else { 20.8431 }; let autumn_base = if year < 1980 { 23.2588 } else { 23.2488 }; let leap_base = if year < 1980 { 1983 } else { 1980 }; let shift = 0.242194 * (year - 1980) - (year - leap_base) / 4; h[date(year, 3, floor(spring_base + shift))] = "春分の日"; h[date(year, 9, floor(autumn_base + shift))] = "秋分の日"; h[date(year, 5, 3)] = "憲法記念日"; if year >= 2007 { h[date(year, 5, 4)] = "みどりの日"; } h[date(year, 5, 5)] = "こどもの日"; h[date(year, 11, 3)] = "文化の日"; h[date(year, 11, 23)] = "勤労感謝の日"; if year >= 1966 { h[date(year, 9, if year >= 2003 { monday(year, 9, 3) } else { 15 })] = "敬老の日"; let sport = if year == 2020 { date(year, 7, 24) } else if year == 2021 { date(year, 7, 23) } else { date(year, 10, if year >= 2000 { monday(year, 10, 2) } else { 10 }) }; h[sport] = if year >= 2020 { "スポーツの日" } else if year == 2019 { "体育の日(スポーツの日)" } else { "体育の日" }; } if year >= 1996 { let sea = if year == 2020 { date(year, 7, 23) } else if year == 2021 { date(year, 7, 22) } else { date(year, 7, if year >= 2003 { monday(year, 7, 3) } else { 20 }) }; h[sea] = "海の日"; } if year >= 2016 { h[date(year, 8, if year == 2020 { 10 } else if year == 2021 { 8 } else { 11 })] = "山の日"; } // 即位・成婚等の特例。 if year == 1959 { h[date(year, 4, 10)] = "結婚の儀"; } if year == 1989 { h[date(year, 2, 24)] = "大喪の礼"; } if year == 1990 { h[date(year, 11, 12)] = "即位礼正殿の儀"; } if year == 1993 { h[date(year, 6, 9)] = "結婚の儀"; } if year == 2019 { h[date(year, 5, 1)] = "休日(祝日扱い)"; h[date(year, 10, 22)] = "休日(祝日扱い)"; } let national = h; let first = date(year, 1, 1); // 祝日に挟まれた日:1986 年から適用、日曜日は対象外。 if year >= 1986 { for day in 0..days_in_year(year) { let d = add_days(first, day); if weekday(d) != 0 && !h.contains(d) && national.contains(add_days(d, -1)) && national.contains(add_days(d, 1)) { h[d] = "休日"; } } } // 振替休日:1973 年導入、2007 年以降は次の祝日でない日まで繰り越す。 for d in national.keys() { if d >= "1973-04-12" && weekday(d) == 0 { let substitute = add_days(d, 1); if year >= 2007 { while h.contains(substitute) { substitute = add_days(substitute, 1); } } if !h.contains(substitute) { h[substitute] = "休日"; } } } h }