旧暦・六曜について(後編)
これは株式会社TimeTree Advent Calendar 2024の4日目の記事です。前編はこちら。
前編では「旧暦」や「二十四節気」や「天保暦」といったかなりマニアックなテーマについて書きました。後編である本記事はもっとマニアックな話になります…。いきなり後編について書くと混乱すると思いますので、簡単に前編の内容について振り返りたいと思います。
- 旧暦とは
- 月の満ち欠けを基にした暦システムで「太陰暦」とも呼ぶ
- 主に東アジアの文化行事に使われている
- 太陰暦の季節のずれを補正するため、太陽の運行を考慮したものが「太陽太陰暦」
- 「二十四節気」は中国で生まれた太陰太陽暦のひとつ
- 日本では六曜の計算に二十四節気をベースとした「天保暦」が使われている
- TimeTreeでは旧暦表示や六曜表示機能を実装している
本記事では旧暦の仕組みや、運用上の課題、グローバル対応の難しさについて解説します。
2033年問題
これまで旧暦は二十四節気の例外が発生する際に、天保暦の追加ルールを適用して運用されてきました。ところがこの追加ルールでも矛盾が出てしまうケースが将来発生する事が分かっています。それが2033年問題です。
こちらの図をご覧ください。
2033年問題
こちらは2033年から2034年にかけた図ですが、青枠のところに注目してください。8月23日、12月22日、2034年2月19日の3つの朔(さく)がいずれの中気にも含まれていません。また、11月22日の朔には旧10月と旧11月の中気が含まれており、2034年1月20日の朔には旧12月、翌旧1月の中気が含まれています。めちゃくちゃややこしいことになっているのがお分かりでしょうか。
天保暦の追加ルールによると「9月23日の朔は秋分を含むため旧8月」「11月22日の朔は冬至を含むため旧11月」ということになりますが、その間に旧9月と旧10月を入れようとしても10月23日の朔の1つしかないため、月名を決定できません。このような事態は1844年の天保暦導入後初めて起こることです。これがいわゆる「2033年問題」で、問題解決のために主に3案が提案されています。
朔 | 案1 | 案2 | 案3 |
---|---|---|---|
2033/7/26 | 7月 | 7月 | 7月 |
2033/8/25 | 8月 | 閏7月 | 8月 |
2033/9/23 | 9月 | 8月 | 9月 |
2033/10/23 | 10月 | 9月 | 10月 |
2033/11/22 | 11月 | 10月 | 11月 |
2033/12/22 | 閏11月 | 11月 | 12月 |
2034/1/20 | 12月 | 12月 | 1月 |
2034/2/19 | 1月 | 1月 | 閏1月 |
2034/3/20 | 2月 | 2月 | 2月 |
旧暦は日本ではすでに廃止された扱いのため、公的機関が矛盾解消のための追加ルールを発表することはありません。この状況下でカレンダー業界各社は六曜のために旧暦を計算する必要があります。ただしありがたいことに「一般社団法人日本カレンダー暦文化振興協会」から、案1の閏11月を推奨するという見解が発表されています。日本カレンダー暦文化振興協会は国立天文台やカレンダー出版業界団体の長などが参加している団体です。この見解はカレンダー業界の中では強い影響力を待つと思われます。
ちなみに中国では、前編で述べたように春節が公的に休みとなるため、公的機関によって旧暦ルールが運用されています。そもそも中国の時憲暦では「冬至を含む月から次に冬至を含む月までに13か月ある場合に,中気が入らない最初の月を閏月とする」というシンプルな追加ルールとなっており、2033年問題は発生しません。
タイムゾーンによって旧暦がずれる?
さて、日本のカレンダーだけで六曜を表示するのであればあまり関係ないのですが、TimeTreeはグローバルに展開をしているサービスなので、旧暦は中国や韓国を考慮する必要があります。中国(UTC+08:00)と日本や韓国(UTC+09:00)は1時間の時差がありますが、日本で0時は中国では前日の23時となり日付が変わります。朔や中気は日付のみを考慮し、時刻は使いません。これによって旧暦の日付がタイムゾーンによりずれることがあります。
タイムゾーンによって「日」がずれるパターン
朔(新月)とは地球中心から見た太陽の中心と、月の中心の黄道座標の経度が同じになった瞬間です。そのため定義上は地球上のどこにいても新月は同時に発生します。時間軸では同じ瞬間でも各国にはタイムゾーンがあるため、それを元に計算された旧暦も変わることがあります。
以下が実際にずれが起きている例になります。朔の時刻を併記すると分かりやすいでしょう。2013年の旧暦5月1日は中国では2013年6月8日ですが、日本や韓国では6月9日になります。中国と日本のタイムゾーンの違いにより、朔がちょうど日付をまたいでおり、そのため旧暦が1日ずれてしまうのです。
太陽暦 | 旧暦(中国) | 旧暦(日本) |
---|---|---|
2013年6月7日 | 旧暦4月29日 | 旧暦4月29日 |
2013年6月8日 |
旧暦5月1日 (朔 2013年6月8日 23:56) |
旧暦4月30日 |
2013年6月9日 | 旧暦5月2日 |
旧暦5月1日 (朔 2013年6月9日 0:56) |
タイムゾーンによって「月」がずれるパターン
二十四節気の区切りは太陽の黄道の角度を基に計算されるため、こちらも特定の中気を通過する瞬間があり、それはタイムゾーンの影響を受けます。地域によって中気の日付が変わると、結果として月がずれてしまうことがあります。2017年の例を見てみましょう。
中気(中国) | 朔(中国) | 中気(日本) | 朔(日本) |
---|---|---|---|
🔴夏至(旧5月) 2017年6月21日 12:24 |
🌚2017年5月26日 3:44 →旧5月1日 |
🔴夏至(旧5月) 2017年6月21日 13:24 |
🌚2017年5月26日 4:44 →旧5月1日 |
🔴大暑(旧6月) 2017年7月22日 23:15 |
🌚2017年6月24日 10:31 →旧6月1日 |
(中気なし) | 🌚2017年6月24日 11:31 →旧閏5月1日 |
(中気なし) | 🌚2017年7月23日 17:46 →旧閏6月1日 |
🔴大暑(旧6月) 2017年7月23日 0:15 |
🌚2017年7月23日 18:46 →旧6月1日 |
🔴処暑(旧7月) 2017年8月23日 5:20 |
🌚2017年8月22日 2:30 →旧7月1日 |
🔴処暑(旧7月) 2017年8月23日 6:20 |
🌚2017年8月22日 3:30 →旧7月1日 |
左2列は中国、右2列は日本です。中国標準時間で2017年7月22日 23:15の中気(大暑)は6月24日の朔に含まれますが、日本時間では中気が7月23日 00:15になり、7月23日の朔と同じ日に来てしまいます。その結果中国では6月24日の朔が旧6月、7月23日の朔が旧閏6月となりますが、日本では6月24日の朔が旧閏5月、7月23日の朔が旧6月となるのです。
ここで挙げた2017年のずれは、TimeTreeのiOSアプリで実際に不具合報告として発覚したものです。iOSの内蔵フレームワークに中国歴を扱う機能があり、それを利用して六曜を計算していたため、日本で一般に販売されているカレンダーと六曜が異なってしまうという不具合でした。これを機に私たちは日本の旧暦計算のための独自実装を追加しました。
六曜について
六曜は旧暦をベースに計算されているというのは前述の通りですが、旧暦さえ算出されていれば六曜の計算は意外と簡単です。まずは六曜を割り当てる仕様を見てみましょう。
六曜は「先勝→友引→先負→仏滅→大安→赤口」の順で繰り返すが、旧暦の毎月1日の六曜は以下のように固定されている。閏月は前の月と同じになる。
月名 六曜 旧1月・旧7月 先勝 旧2月・旧8月 友引 旧3月・旧9月 先負 旧4月・旧10月 仏滅 旧5月・旧11月 大安 旧6月・旧12月 赤口
一見すると複雑に見えますが、計算式に表すと (旧暦の月
+ 旧暦の日
) ÷ 6 の余りを順番に 0=大安、1=赤口、2=先勝... と割り当てていくだけです。例えば旧暦10月15日は (10 + 15) % 6 = 1
= 赤口
となります。六曜の計算自体はシンプルですが、旧暦の計算結果がそのまま六曜に影響します。これまでお伝えしてきた2033年問題や、タイムゾーンによる「ずれ」が無視できないという問題がご理解いただけたでしょうか。
TimeTreeでの実装
旧暦をまともに計算しようとすると、朔や中気を計算するために月と地球と太陽の天体運動を計算式として落とし込む必要があり、難易度も高く計算量も膨大になります。TimeTreeでは実装をシンプルにするため、1900〜2050年までのデータに絞って事前に計算された閏月や月数のデータをクライアントコード内に持つというやり方をとっています。これで通信も必要なく高速にカレンダー上に旧暦の日付や六曜を表示することができました。
また、海外の一部の国で需要のある旧暦の繰り返し機能ですが、こちらはRFC 5545のiCalendarの仕様のひとつ、RDATE
を使って事前に計算された日付を数年分繰り返しデータとして含めるという方法をとっています。
まとめ
いかがでしたでしょうか。前後編に渡って旧暦を扱う難しさをお伝えしてきました。TimeTreeのエンジニアでも旧暦を正しく理解しているメンバーは少ないため、旧暦関連の不具合に遭遇したらまずはこの記事を参照してもらおうと思います。笑
参考文献
TimeTreeのエンジニアによる記事です。メンバーのインタビューはこちらで発信中! note.com/timetree_inc/m/m4735531db852
Discussion