12時02分01秒 [ソフト開発]
ある日付が休日かどうかを判定するには
その日が休日かどうかを調べるには前後の数日も見ないといけない
平日と休日を区別するタイプの(つまり壁掛け等の紙製で一般的な)カレンダーをプログラムで生成しようと思うと、「いつが平日でいつが休日なのか」を何らかの方法で判定する必要があります。
ある1つの日付を入力するだけで「その日が休日かどうか」を判定する処理はそんなに難しくないだろうと当初は高をくくっていたのですけども、いざプログラムを書こうと思うと、「振替休日」と「国民の休日」という2種類の臨時休日の判定が意外と複雑で、単一の日付だけを突然指定されても「その日が休日なのかどうか」は分からないことが分かりました。(^_^;;;
少なくとも「調べたい日の直前の日曜日」から「調べたい日の翌日」までの毎日が、それぞれ休日なのか平日なのかを順に調べないと特定できなさそうです。
▼祝日だけならリストなり計算なりで分かるが
曜日は世界共通で簡単に計算できますし、日付が指定されている祝日(例えば2月10日が「建国記念日」とか)はリストを持っておけば簡単に分かります。
そのほか、ハッピーマンデーによる祝日(例えば1月の第2月曜日が「成人の日」とか)は「曜日」と「第何週か?」を計算すれば分かりますし、年によって微妙に変化する祝日(例えば3月19日~22日あたりになる「春分の日」とか)も専用の計算式を使えば判別できます。
なので、「祝日かどうか」を判断すれば良いだけなら、ある1つの日付を指定されるだけで判別可能なのですよね。
でも、「休日かどうか」を判断するには、それだと足りません。
振替休日はほとんどが月曜日だが、火曜日や水曜日になる場合もある
「振替休日」は、祝日が日曜日と重なった場合に「次の平日」が休日になる制度です。ほとんどの振替休日は月曜日になりますが、(2022年現在の祝日リストでは)5月の連休時だけは祝日が連続しますから、火曜日や水曜日が振替休日になる可能性があります。(※下図の緑色矢印部分が振替休日)
なので、祝日リストを持っているだけではダメで、「調べたい日の直前の日曜日」から当日までの状況を調べてからでないと「今日が休日なのか平日なのか」が特定できません。
いや、2022年現在の日本の祝日だけに限定して構わないならそこまでしなくても良いのですけども。
▼「汎用的に作りたいなら」の話
2022年現在の日本では、日付固定で祝日が連続しているのはゴールデンウィークを構成する5月3日・4日・5日だけですから、振替休日が火曜日や水曜日になる可能性がある日は5月6日しかありません。たぶん(日曜日と重なった祝日の翌日に、ハッピーマンデーでの祝日が来るような日があるとしたら別ですが、なさそうな気がしています)。
なので、「5月6日」の曜日を調べさえすれば『その日が月・火・水のどれかなら確実に振替休日』だと判別できます。
しかし、将来的に新たな祝日が作られるケースも想定して汎用的なカレンダー生成プログラムにしたいなら、そこを決め打ちにするわけにはいきません。したがって、「指定日の直前の日曜日」が祝日と重なっているかどうかを調べて、そこから「指定日」までのすべての日が祝日なのかどうかを調べる必要がありそうです。
国民の休日を判定するには、その日の曜日と、前後の1日を調べる必要がある
「国民の休日」は祝日と祝日に挟まれた1日が休日になる規則です。でも、祝日と祝日に挟まれた1日が日曜日の場合には特に何もなくただの日曜日になるだけです。また、最初の祝日が日曜日の場合には、間の1日は「振替休日」になるだけであって「国民の休日」にはなりません。(いや、どちらが優先されるのかはハッキリとは分からないのですが、既存のカレンダーを見るとそんな気がします。法的には(後述しますが)単に「休日」という定義があるだけで、「振替休日」とか「国民の休日」とかの名称は存在しないので……。)
なので、調べたい日の前日と翌日が祝日かどうかを確認してから、その日が日曜日または振替休日ではないことを確認する必要があります。
昔はこの規則によって5月にゴールデンウィークが構成されていましたが、今では5月の連休は本当に「3連続の祝日」に変更されましたからこの規則は使われていません。しかし、数年に1回だけ、この規則によって9月にシルバーウィークができます(次回は2026年です)。
(▲次のシルバーウィークは、2026年9月22日が「国民の休日」になることで発生します。)
▼前後の1日を確認するだけでは不十分なケースも将来にはあり得るかも
今の日本の祝日リストには存在しませんが、仮に[➊祝日]→[➋祝日]→[➌平日]→[➍祝日]のような並びの4日間が発生する場合、たいていの年で➌は「国民の休日」になりますが、➋が日曜日の場合だけでなく、➊が日曜日な場合でも、➌は「振替休日」になるため、「国民の休日」にはなりません。このようなパターンにも対応しようと思うと、前後の1日だけを確認するのでは不十分で、「調べたい日」から1日ずつ「次に平日が現れる時点」まで遡って確認する必要がありますね……。
振替休日と祝日に挟まれた1日は「国民の休日」にはならない?
2022年現在の祝日規則上では発生しなさそうですが、祝日の追加や変更等で今後にもし『振替休日と祝日に挟まれた平日1日』が発生することがある場合、その日が「国民の休日」になるのかがちょっと気になります。
例えば、[➊祝日]→[➋平日]→[➌平日]→[➍祝日]のような並びの4日間があれば、➊が日曜日のときに➋が振替休日になるため、➌は『振替休日と祝日に挟まれた平日1日』になります。
▼日本の祝日を定義する法律を調べると……
日本の祝日は「国民の祝日に関する法律」という法律で定義されていまして、この第3条第3項に
その前日及び翌日が「国民の祝日」である日(「国民の祝日」でない日に限る。)は、休日とする。
……と書かれているので、「国民の休日」が発生します。この法文での「国民の祝日」というのは要するに一般的に言われる「祝日」のことです。「国民の休日」と紛らわしいですが。法律では「国民の休日」という名称は使われていなくて、単に「休日」としか書かれていないのですよね。「国民の休日」という名称がどこから出てきたのかよく分かりませんけども。^^;
- 一般的に言われる「祝日」 → 法律では「国民の祝日」と記載
- 一般的に言われる「国民の休日」 → 法律では「休日」と記載
で、この法文では「国民の祝日」と「休日」とを分けて扱われています。第3条第3項の定義だと「前日と翌日の両方が『国民の祝日』の場合」でだけ、間の1日を休日にすると書かれていますから、「前日が休日(=国民の休日)」の場合には該当しなさそうですね。
なので、『振替休日と祝日に挟まれた平日1日』が発生することがあっても、少なくとも2022年現在の法律では、その日は平日のままっぽいです。
私のカレンダープログラムでは
私が作って先日リリースしたカレンダーCGI「さんごよみ」では、結局、日付から判定するのではなくて、1ヶ月分のカレンダーをまずは生成してから、1日ずつ祝日規則を適用して休日になるかどうかを判定するようにしました。
手順はだいたい以下のような感じです。
- 1ヶ月のカレンダーは最大で6週間分の空間を使います(1日が土曜日の場合は30日が第6週になります)から、7列×6行(=曜日×週)の配列をまずは確保しておきます。
- 当月1日の曜日を計算して、当月が何日まであるのかを調べれば(2月だけは閏年の計算が必要です)、1ヶ月分のカレンダーを生成できます。
- 祝日規則に沿った祝日を適用してみます。(日付固定の祝日ならその日に割り当てれば良いだけですし、ハッピーマンデーでの祝日なら指定週の月曜日に割り当てれば良いだけですし、春分の日や秋分の日のような計算式で求められる祝日なら計算して割り当てれば良いだけです。)
- 日曜日と祝日が重複するケースが出てくれば、次の平日を探して(必ずしも翌日とは限りません)そこを休日「振替休日」にします。
- 祝日と祝日の間が1日だけのケースを見つけたら、その間の1日が日曜日や振替休日ではない場合に限って、そこを休日「国民の休日」にします。
……というような感じでカレンダーを生成させました。
あと、臨時の祝日移動規則にも対応させたり、任意の休日を定義できるようにもしましたから、実際のカレンダー生成処理はもっと続くのですが。
結構面倒くさいです。(^_^;)
ただ、この方法だと「1ヶ月単位」でしか考えていないので、「前月31日が祝日」&「今月2日が祝日」というような『月をまたぐ判定』が必要なケースが将来発生した場合、その間にある「今月1日は国民の休日」という判定はできない問題があるのですが。そういう面倒な祝日規則は作らないで頂けると嬉しいです。(笑)
月末を祝日にするのはできるだけ避けて欲しいですね……。^^;
将来的にそういう状況が発生するような祝日が新設されたり移動されたりしたら、またカレンダー生成プログラム製作者が苦労しそうです。……いや、苦労するかどうかは分かりませんけども、少なくともプログラムはアップデートする必要があるでしょう。(^_^;;;
祝日規則はシンプルに……!
2020年と2021年には臨時に祝日が移動する法律ができて一時的に祝日が変化しましたけども、そのような祝日の臨時移動に対応できるカレンダープログラムはそうそうない気がします。祝日リストを編集できるプログラムはあるでしょうけども、「ある特定の年だけは異なる祝日リストを使う」というような状況を事前に想定しているプログラムはさすがになかったのではないでしょうかね……?
拙作のカレンダーCGIではその規則にも対応したのですけども、なかなか手間が掛かりました。その辺は、先日の記事『カレンダー表示フリーCGI「さんごよみ」開発裏話』に書いています。
何にせよ、祝日規則はシンプルにして頂きたいです。(^_^;;;