和暦

2024年4月24日更新
昔、それもかなり昔、そうあれはXPの頃では無かったかと…。
Accessで万年カレンダーを作った事が有りました。
只の万年カレンダーではなく付加情報満載の気合が入ったものです。
和暦や旧暦は勿論の事、二十四節気をはじめとして雑節や六曜など、
多くの情報を表示した「高島暦」の様な物でした。
まぁ、和暦を扱う以上は万年カレンダーは無理なのですが…。

当時のVBAでできたのですからプロデルなら勿論可能でしょうが、
予想を超えてプログラムを組まずとも和暦や旧暦は勿論の事で、
何と六曜まで取得可能なのには驚きました。

カレンダーは天文学と密接に関係しているので、
面倒な内容の計算が避けられず誤差の処理との闘いです。
それが必要になる度に同じようなコーディングをしたく無いので、
プロデルに依る再チャレンジは汎用性を重視したいと考えています。
それでは使い勝手の良いDLLの完成を目指して制作開始です。
[ 01 和暦関連の機能を調査 ]
先ずはプロデル標準装備の和暦の機能を見てみます。
値は、「2024/4/7」を日時形式化
 和暦は、値を「ggy年M月d日(ddd)」に整えたもの
 和暦を表示する

何とこれだけで「令和6年4月7日(日)」と表示されました。
また、「ggyy年M月d日(dddd)」の様に指定すると、
「令和06年4月7日(日曜日)」といった表示も可能です。

次は同じ日の旧暦を和暦形式で表示してみます。
旧暦表示は、値の旧暦を「ggy年M月d日(ddd)」に整えたもの
 旧暦表示を返す

結果は「令和6年2月29日(木)」となりました。

最後は六曜を求めてみました。
値は、「2024/4/7」を日時形式化
 値の六曜を表示する

此方は更に簡単に「赤口」と表示されました。

一度作った事が有るものを再度作るのは抵抗が有るのですが、
これで少しは抵抗感が和らいだ気がします。
[ 02 自力で和暦換算を遣ってみる ]
高島暦風のカレンダーを作る為の取り組みは、
和暦や六曜の機能が既にプロデルに備わっていたので幸先の良いスタートです。
しかし、この先に待っている二十四節気や九星などの取得処理を考えると、
肩慣らしをしておいた方が良さそうに思えて来ました。
そこで折角用意されている機能をあえて使わないで組んでみます。

先ずは西暦を和暦に変換する方法を考えます。
変換と言っても和暦は厳密な法則で決められるわけでは無いので、
ケースバイケースの処理になります。
明治・大正・昭和・平成・令和の期間から算出する事になります。

明治は1868年10月23日から1912年7月30日までの45年間。
大正は1912年7月30日から1926年12月24日までの15年間。
昭和は1926年12月25日から1989年1月7日までの64年間。
平成は1989年1月8日から2019年4月30日までの31年間。
令和は2019年5月1日水曜日から始まりました。

これ等の期間を整数値に直すと下記になります。
589423392000000000〜603234432000000000
603234432000000000〜607779072000000000
607779936000000000〜627357312000000000
627358176000000000〜636921792000000000
636922656000000000〜

以上を踏まえてプログラムにしたものが下記になります。
【日付:文字列】を和暦へ換算するの手順
  値は、日付を日時形式化
  シリアルは、値の整数値
  年は、値の年
  月は、値の月
  日は、値の日
  年数字は、(年の内容の3文字目から2文字取り出したもの)の整数
  もし(シリアル>=589423392000000000)、
  &かつ(シリアル<=603234432000000000)なら
   もし(シリアル=603234432000000000)なら
    和暦は、「明治[年数字+33]年[月]月[日]日(大正元年)」
   そうでないなら
    和暦は、「明治[年数字+33]年[月]月[日]日」
   もし終わり
  他でもし(シリアル>=603234432000000000)、
  &かつ(シリアル<=607779072000000000)なら
   和暦は、「大正[年数字-11]年[月]月[日]日」
  他でもし(シリアル>=607779936000000000)、
  &かつ(シリアル<=627357312000000000)なら
   和暦は、「昭和[年数字-25]年[月]月[日]日」
  他でもし(シリアル>=627358176000000000)、
  &かつ(シリアル<=636921792000000000)なら
   和暦は、「平成[年数字+12]年[月]月[日]日」
  他でもし(シリアル>=636922656000000000)なら
   和暦は、「令和[年数字-18]年[月]月[日]日」
  もし終わり
  和暦を返す
 終わり

結構面倒な処理が必要でした。
[ 03 和暦換算を簡略化してみた ]
前回の和暦換算は精度を重視したので取っ付き難い感じになってしまいました。
通常は精度を落とした簡略化されたものでも良さそうです。
【西暦:数値】年を和暦へ換算するの手順
  値は、(西暦の内容の3文字目から2文字取り出したもの)の整数
  もし(西暦>=1868)かつ(西暦<=1912)なら
   もし(値+33>=100)なら
    和暦は、「明治[値-100+33]年」
   そうでないなら
    和暦は、「明治[値+33]年」
   もし終わり
  他でもし(西暦>=1912)かつ(西暦<=1926)なら
   和暦は、「大正[値-11]年」
  他でもし(西暦>=1926)かつ(西暦<=1989)なら
   和暦は、「昭和[値-25]年」
  他でもし(西暦>=1989)かつ(西暦<=2019)なら
   和暦は、「平成[値+12]年」
  他でもし(西暦>=2019)なら
   和暦は、「令和[値-18]年」
  もし終わり
  和暦を返す
 終わり


随分と読み易くなりました。
元号の変わり目が曖昧になる欠点がありますが、
通常はこれで問題無さそうです。
[ 04 和暦を西暦に換算してみた ]
今回は和暦を西暦に換算してみます。
前回とは真逆の操作をする事で可能です。
【和暦:文字列】を西暦へ換算するの手順
  元号は、和暦の内容の1文字目から2文字取り出したもの
  文字数は、和暦の文字数
  終端位置は、和暦の内容から「年」を探したもの
  もし(終端位置が0)なら
   有効文字数は、文字数-2
  そうでないなら
   有効文字数は、文字数-3
  もし終わり
  値は、(和暦の内容の3文字目から[有効文字数]文字取り出したもの)の整数
  もし(元号が「明治」)なら
   西暦は、1867+値
  他でもし(元号が「大正」)なら
   西暦は、1911+値
  他でもし(元号が「昭和」)なら
   西暦は、1925+値
  他でもし(元号が「平成」)なら
   西暦は、1988+値
  他でもし(元号が「令和」)なら
   西暦は、2018+値
  もし終わり
  もし(終端位置が0)なら
   「[西暦]」を返す
  そうでないなら
   「[西暦]年」を返す
  もし終わり
 終わり


こちらも略式なら簡単です。
[ 05 旧暦を補正する ]
今回は旧暦に関してです。
プロデルはデフォルトで旧暦を取得可能です。
しかし、詳しく検証したら特定の条件下で正しい旧暦を得られませんでした。
簡単な補正で正しい旧暦を求められます。
【日付:文字列】から旧暦を計算するの手順
  値は、日付を日時形式化
  年は、値の年
  月は、値の月
  旧暦は、値の旧暦
  日は、旧暦の日
  もし(月<3)なら
   年=年-1
  もし終わり
  補正旧暦は、「[年]/[旧暦の月]/[旧暦の日]」を日時形式化
  補正旧暦を返す
 終わり

[ 06 自前で六曜を取得してみる ]
今回は六曜を自前で取得してみます。
六曜は旧暦を基準にしているので前回作成した手順が使えます。
六曜は朔日の曜が決められていてそこからの繰り返しなので、
六曜の配列を用意して計算で取得可能です。
【日付:文字列】から六曜を取得するの手順
  結果は、[日付]から旧暦を計算する
  開始位置は、結果の月を6で割った剰り
  もし(開始位置が0)なら
   開始位置は、6
  もし終わり
  参照値は、結果の日を6で割った剰り
  番号は、(開始位置+参照値-1)を6で割った剰り
  曜一覧は、{「先勝」,「友引」,「先負」,「仏滅」,「大安」,「赤口」}
  曜一覧(番号)を返す
 終わり


決め事に忠実にコーディングをしましたが、
もう少し端折れそうなので遣ってみました。
【日付:文字列】から六曜を取得するの手順
  結果は、[日付]から旧暦を計算する
  番号は、(結果の月+結果の日-1)を6で割った剰り
  曜一覧は、{「先勝」,「友引」,「先負」,「仏滅」,「大安」,「赤口」}
  曜一覧(番号)を返す
 終わり


大分すっきりと書く事ができました。
[ 07 基本のユリウス通日を計算する ]
新旧東西の暦が存在する中で日本では明治以降グレゴリオ暦が導入されました。
また、同時に和暦も併用されているので時に混乱を招く事も有ります。
天体由来の暦は誤差への工夫を重ねて利用されて来ました。
閏年や閏秒などもそうですが閏秒は廃止される事が決定した様です。
その理由が「コンピュータが誤作動するから」と言うので笑えます。

話を本題に戻します。
今回はユリウス通日の算出ですが多くの人が計算精度を求めた結果、
ユリウス通日を算出する式に使用する補正値が複数存在します。
【日付:文字列】のユリウス通日を取得するの手順
  値は、日付を日時形式化
  年は、値の年
  月は、値の月
  日は、値の日
   もし月が3未満なら
     年を減らす
     月を12だけ増やす
   もし終わり
  JDN1=1721088.5 +(365.25*年)の整数-([年]/100)の整数
  JDN2=([年]/400)の整数+(30.59*([月]-2))の整数+[日]
  JDN=JDN1+JDN2
  JDNを返す
 終わり


ユリウス通日に関してはもう一つ注意すべき事が有ります。
ユリウス通日の取得には時間も重要です。
午前と午後では1日違って来ます。
それは何故か正午を起点としたからのようですが理由は知りません。
尚、ユリウス通日は桁数が大きな数字になるので、
より扱いやすくした修正ユリウス日と言うものが有ります。
修正ユリウス日=ユリウス通日-2400000.5
[ 08 日付から曜日を算出する ]
今回は「2024/4/12」のような文字列から曜日を算出します。
プロデルには曜日や曜日番号を取得する機能が備わっているので、
敢えてこの機能を実装する必要はないのですが何事も経験です。

曜日はツェラーの公式を使えば簡単に求められます。
日付を「年」と「月」と「日」の要素に分解して計算します。
結果は曜日の番号になるので曜日に置き換えて完了です。
【日付:文字列】から曜日を取得するの手順
  日時は、日付を日時形式化
  年は、日時の年
  月は、日時の月
  日は、日時の日
  ' ツェラーの公式
  h=(日+(26*(月+1)/10)+年+(年/4)-(年/100)+5)の整数 を7で割った剰り
  ' 曜日番号を曜日に置き換える
  曜日一覧は、{「日」,「月」,「火」,「水」,「木」,「金」,「土」}
  曜日は、曜日一覧(h) & 「曜日」
  曜日を返す
 終わり

[ 09 干支を取得する ]
今回は和暦には欠かせない干支に関してです。
一口に干支と言っても色々と有るようです。
現代で干支と言えば動物を表す一文字を指す事が多いですが、
昔の人は良く何々の干支というような言い方をしていました。
例えば今年(2024)は辰年ですが昔は「甲辰」とも言われていました。
この「甲」の部分を十干と言い「辰」の部分を干支と言うようです。

さて、此処からは本題で西暦の「年」から干支を取得します。
一応、十干と干支を合わせた昔ながらの形式にします。
現代風に使いたい場合は最初の一文字を削除すれば済みます。
また、干支には月の干支や日の干支も有るようですが、
経験上使った事が無いので今回はスルーします。
【日付:文字列】から干支を取得するの手順
  日時は、日付を日時形式化
  年は、日時の年
  十干一覧は、{「庚」,「辛」,「壬」,「癸」,「甲」,「乙」,「丙」,「丁」,「戊」,「己」}
  干支一覧は、{「申」,「酉」,「戌」,「亥」,「子」,「丑」,
        「寅」,「卯」,「辰」,「巳」,「午」,「未」}
  十干は、十干一覧(年を10で割った剰り+1)
  干支は、干支一覧(年を12で割った剰り+1)
  十干&干支を返す
 終わり

[ 10 九星を取得する ]
今回は九星を取得します。
九星は日付や天体とも関係あるので広義に捉えて暦の要素としましたが、
誕生日や占いに関係する内容なのでカレンダーに使う予定は有りません。
九星は誕生日から「本命星」を導き出します。
九星気学では必ずと言って良い程に誕生日を訊かれますが、
「本命星」の導出には年情報だけで月や日は必要ありません。

【日付:文字列】から九星を取得するの手順
  日時は、日付を日時形式化
  年は、日時の年
  四桁合計値は、0
  番号を1から増やしながら4まで繰り返す
   四桁合計値は、四桁合計値+(「[年]」の[番号]文字目から1文字取り出したもの)
  繰り返し終わり
  もし(四桁合計値>9)なら
   四桁合計値は、(「[四桁合計値]」の1文字目から1文字取り出したもの)+
    (「[四桁合計値]」の2文字目から1文字取り出したもの)
  もし終わり
  九星一覧は、{「一白水星」,「二黒土星」,「三碧木星」,「四緑木星」,
   「五黄土星」,「六白金星」,「七赤金星」,「八白土星」,「九紫火星」}
  九星一覧(11-四桁合計値)を返す
 終わり

[ 11 和風月名を取得する ]
今回は和風の月名を取得してみます。
本来なら早期に盛り込むべき機能です。
普段は数字で表した月名を使う事が多くそれに慣れてしまっていますが、
和風月名は柔らかい響きと共に季節感も有り個人的には好みです。

【月名:文字列】の和風月名を取得するの手順
  月名が「月」で終わらないなら手順を抜ける
  数字部は、月名の末尾から1文字消したもの
  漢数字一覧は、{「一」,「二」,「三」,「四」,「五」,「六」,「七」,「八」,「九」,
   「十」,「十一」,「十二」}
  全角数字一覧は、{「1」,「2」,「3」,「4」,「5」,「6」,「7」,「8」,「9」,
   「10」,「11」,「12」}
  大字一覧は、{「壱」,「弐」,「参」,「肆」,「伍」,「陸」,「漆」,「捌」,「玖」,
   「拾」,「拾壱」,「拾弐」}
  結果は、漢数字一覧から数字部を探す
  もし(結果が「{}」)なら
   結果は、全角数字一覧から数字部を探す
   もし(結果が「{}」)なら
    結果は、大字一覧から数字部を探す
   もし終わり
  もし終わり
  和風月名一覧は、{「睦月」,「如月」,「弥生」,「卯月」,「皐月」,「水無月」,
   「文月」,「葉月」,「長月」,「神無月」,「霜月」,「師走」}
  和風月名一覧(結果(1))を返す
 終わり


今回は少しばかりエラー処理を入れてみました。
[ 12 二十四節気を取得する ]
今回は暦関係では最大の難関かも知れない二十四節気を取得します。
天体の動きは一定では無く整数で割り切れる事も稀なので誤差は避けられません。
従って何年も使える二十四節気用の計算式というのは難しいです。
それを修正する為に多くの人が補正して来たようです。
何処かで妥協して使う他に方法が有りません。

それを念頭に式の修正やら定数の微調整を行い数年間分の検証を行いました。
しかし、過去や未来のどの年に対しても正解を出すとは保証できません。
今回作成した手順は今後修正される可能性が有ります。
利用する場合は確定でない事を承知の上でお使いください。

今回は「【年:整数】年の【二十四節気名:文字列】の日付を取得する」と、
「【年:整数】年の二十四節気を取得する」の二つを作成しました。
和暦用ライブラリは後少しで完成です。
[ 13 雑節を取得する ]
今回は雑節を取得します。
雑節は二十四節気と密接に関係しているので、
先ずは二十四節気を取得してそこから導き出します。
只、「土用」に関しては太陽黄経の値を基にしているのですが、
日付の境目では無いので判定時刻により一日の誤差を生ずる事が有ります。

和暦関連は未だ未だ在りそうですが普段使いにはこれで十分そうなので、
雑節を以って和暦用ライブラリは打ち切りとします。
ライブラリの形として完成したら公開する予定です。
[ 14 暦ライブラリをテストする ]
暦ライブラリが完成したので総合テストを行っています。
今回はその為のプログラムを作成しました。


これはテスト用に作成したプログラムですが、
そのまま暦ライブラリの使用説明書の代わりとなるものです。
一通りのテストが終了したら此処ではなく
「開発お助けソフト」の方で公開する予定です。