PHPで二十四節気・七十二候一覧を作成

(1/1)
PHPで視黄経を算出するプログラムを作り、指定した年の二十四節気、節分および七十二候の一覧を求めることを目標にする。

(2023年2月11日)getSolarTerm72() 表記改訂:水澤腹堅→水沢腹堅。節分の月日表記の不具合修正。
(2023年2月4日)表記改訂:七十二候
(2023年1月14日)計算精度を向上した。数値入力にSpinner、pahooInputDataを導入した。

目次

サンプル・プログラムの実行例

PHPで二十四節気・七十二候一覧を作成

サンプル・プログラムのダウンロード

圧縮ファイルの内容
getSolarTerm.phpサンプル・プログラム本体。
pahooCalendar.php暦・潮位計算クラス pahooCalendar。
暦・潮位計算クラスの使い方は「PHPで二十四節気・七十二候一覧を作成」「PHPで月齢を計算」「PHPで日出没・月出没・月齢・潮を計算」「PHPで潮位を計算する」などを参照。include_path が通ったディレクトリに配置すること。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
getSolarTerm.php 更新履歴
バージョン 更新日 内容
1.5.2 2023/02/11 節分の月日表記の不具合修正
1.5.1 2023/01/17 bug-fix
1.5.0 2023/01/14 数値入力にSpinner、pahooInputData導入
1.4.0 2023/01/09 計算精度向上
1.3 2021/01/23 節分を表示,PHP8対応
pahooCalendar.php 更新履歴
バージョン 更新日 内容
4.5.0 2024/03/17 ヒジュラ暦メソッドを追加
4.4.1 2024/03/17 getCabinetOfficeHolidayTable() -- bug-fix
4.4.0 2024/02/25 内閣府の祝日表を参照できるようにした
4.3.2 2023/02/11 getSolarTerm72() 表記改訂:水澤腹堅→水沢腹堅
4.3.1 2023/02/03 表記改訂:バクムーン→バックムーン,スタージャンムーン→スタージョンムーン,七十二候
pahooInputData.php 更新履歴
バージョン 更新日 内容
1.5.0 2024/01/28 exitIfExceedVersion() 追加
1.4.2 2024/01/28 exitIfLessVersion() メッセージ修正
1.4.1 2023/09/30 コメントの訂正
1.4.0 2023/09/09 $_GET, $_POST参照をfilter_input()関数に置換
1.3.0 2023/07/11 roundFloat() 追加

二十四節気・七十二候とは

二十四節気 (にじゅうしせっき) とは、立春、大暑、小雪など、節分を基準に1年を24等分して約15日ごとに分けた季節のことである。
黄道と太陽
頭の中を天動説に切り替えてほしい。
地球を中心にして、太陽は1年間で地球の周りを1周する。その運動経路を黄道と呼ぶ。左図で傾いた円が黄道である。
黄道座標
黄道を赤道のようにみたてた大きな球(天球)を考える。天球上にある天体の座標をあらわすのに、地図の緯度・経度と同じ考え方で、天の北極・天の南極の間を180度に分割した黄緯、黄道を360度に分割した黄経を用いる。
が、実際の太陽系は、太陽の回りを地球が公転する地動説であるため、同じ黄経・黄緯の位置にある天体でも、地球の位置によって若干のズレ(年周視差)が起き、さらに光の速度が有限であるため、年周光行差となって表れる。同様に、地球の自転による日周光行差もある。
これらの光行差を補正した黄経・黄緯を視黄経視黄緯と呼ぶ。今後、とくに断りの無い場合は視黄経視黄緯で計算しているととらえてほしい。

話を二十四節気に戻すと、この二十四節気というものは、黄道を24等分――太陽は黄道に沿って動くので黄緯は常に0度――つまり、視黄経の15度ごとに区切った点に決められている。
春分が0度で、清明は15度、穀雨は30度‥‥啓蟄は345度である。
また、立春、立夏、立秋、立冬が各季節の始まりとされ、その前日を節分と呼ぶ。現代では立春の前日を節分と呼んでいる。

二十四節気をさらに5日おきに分けて、気象の動きや動植物の変化を知らせるようにしたのが七十二候 (しちゅじゅうひこう) である。

ちなみに「気候」という言葉は、「節気」と「候」に由来する。

準備:初期値など

  36: //指定できる西暦年の範囲
  37: define('MIN_YEAR', 1901);
  38: define('MAX_YEAR', 2099);
  39: 
  40: //世界時からの時差(日本標準時)
  41: define('UTCDIFF', +9.0);
  42: 
  43: //計算期間(月)
  44: define('CALC_TERM', 3);
  45: 
  46: //月齢を計算する時刻
  47: define('CALC_HOUR', 21);
  48: 
  49: //Spinner - jQuery UI を使用するかどうか
  50: define('USESPINNER', TRUE);
  51: 
  52: //数値増減クリックで即判定するかどうか(TRUE:即判定,FALE:判定ボタンを用意)
  53: define('ONCHANGE', FALSE);
  54: 
  55: //表示幅(単位:ピクセル)
  56: define('WIDTH', 550);
  57: 
  58: //require_once()で呼ぶファイルはinclude_pathが通っているフォルダに配置すること.
  59: //暦計算クラス
  60: require_once('pahooCalendar.php');
  61: 
  62: //データ入力に関わる関数群
  63: require_once('pahooInputData.php');

指定できる年の範囲や世界時からの時差を定数として定義しておく。

太陽黄経の計算や、二十四節気・七十二候の計算はユーザークラス "pahooCalendar" に分離した。
オブジェクト生成時に、表示言語として "ja"(日本語)を、世界時との時差としてユーザー定義の定数 UTCDIFF を渡しておく。こうすることで、pahooCalendar クラスが出力する文字列は日本語に、日時計算は時差 UTCDIFF がある前提で計算を行う。

数値入力に jQuery UISpinner を使用している。設定でOFFにすることもできる。Spinner の使い方については、「Spinner - jQuery UI - PHPで素数かどうか判定」をご覧いただきたい。

入力した数値の取得とバリデーションチェックに、ユーザー定義クラス群 "pahooInputData.php" を利用している。

解説:視黄経の算出

 690: /**
 691:  * J2000.0からの経過年数における太陽の視黄経(度)を求める.
 692:  * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-42-01.shtm
 693:  * @param   float $jy J2000.0からの経過年数
 694:  * @return  float 太陽の視黄経(度)
 695: */
 696: function __longitude_sun($jy) {
 697:     $th  = 0.0003 * sin(deg2rad($this->__angle(329.7  +   44.43  * $jy)));
 698:     $th +0.0003 * sin(deg2rad($this->__angle(352.5  + 1079.97  * $jy)));
 699:     $th +0.0004 * sin(deg2rad($this->__angle21.1  +  720.02  * $jy)));
 700:     $th +0.0004 * sin(deg2rad($this->__angle(157.3  +  299.30  * $jy)));
 701:     $th +0.0004 * sin(deg2rad($this->__angle(234.9  +  315.56  * $jy)));
 702:     $th +0.0005 * sin(deg2rad($this->__angle(291.2  +   22.81  * $jy)));
 703:     $th +0.0005 * sin(deg2rad($this->__angle(207.4  +    1.50  * $jy)));
 704:     $th +0.0006 * sin(deg2rad($this->__angle29.8  +  337.18  * $jy)));
 705:     $th +0.0007 * sin(deg2rad($this->__angle(206.8  +   30.35  * $jy)));
 706:     $th +0.0007 * sin(deg2rad($this->__angle(153.3  +   90.38  * $jy)));
 707:     $th +0.0008 * sin(deg2rad($this->__angle(132.5  +  659.29  * $jy)));
 708:     $th +0.0013 * sin(deg2rad($this->__angle81.4  +  225.18  * $jy)));
 709:     $th +0.0015 * sin(deg2rad($this->__angle(343.2  +  450.37  * $jy)));
 710:     $th +0.0018 * sin(deg2rad($this->__angle(251.3  +    0.20  * $jy)));
 711:     $th +0.0018 * sin(deg2rad($this->__angle(297.8  + 4452.67  * $jy)));
 712:     $th +0.0020 * sin(deg2rad($this->__angle(247.1  +  329.64  * $jy)));
 713:     $th +0.0048 * sin(deg2rad($this->__angle(234.95 +   19.341 * $jy)));
 714:     $th +0.0200 * sin(deg2rad($this->__angle(355.05 +  719.981 * $jy)));
 715:     $th += (1.9146 - 0.00005 * $jy* sin(deg2rad($this->__angle(357.538 + 359.991 * $jy)));
 716:     $th +$this->__angle(280.4603 + 360.00769 * $jy);
 717: 
 718:     return $this->__angle($th);
 719: }

 721: /**
 722:  * 指定した日時における太陽の視黄経(度)を求める.(日時はローカル時間).
 723:  * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-42-01.shtm
 724:  * @param   int $year, $month, $day  年月日(グレゴリオ暦)
 725:  * @param   float $hour, $min, $sec 時分秒(ローカル時間)
 726:  * @param   float $tdiff UTCとの時差;NULLの時はTDIFF(省略時NULL)
 727:  * @return  float 太陽の視黄経(度)
 728: */
 729: function longitude_sun($year, $month, $day, $hour, $min, $sec, $tdiff=NULL) {
 730:     $jy = $this->Gregorian2JY($year, $month, $day, $hour, $min, $sec, $tdiff);
 731: 
 732:     return $this->__longitude_sun($jy);
 733: }

計算式は『日の出・日の入りの計算』(長沢工=著)による。

解説:二十四節気の算出

 942: /**
 943:  * 指定した年月日の二十四節気を求める.
 944:  * 二十四節気でなければ空文字を返す.
 945:  * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-42-01.shtm
 946:  * @param   int $year, $month, $day  グレゴリオ暦による年月日
 947:  * @return  string 二十四節気/'' :二十四節気ではない
 948: */
 949: function getSolarTerm($year, $month, $day) {
 950:     static $old = -1.0;
 951:     static $table = array(
 952: 'jp' => array(
 953:   0 => '春分',  1 => '清明',  2 => '穀雨',  3 => '立夏',
 954:   4 => '小満',  5 => '芒種',  6 => '夏至',  7 => '小暑',
 955:   8 => '大暑',  9 => '立秋', 10 => '処暑', 11 => '白露',
 956:  12 => '秋分', 13 => '寒露', 14 => '霜降', 15 => '立冬',
 957:  16 => '小雪', 17 => '大雪', 18 => '冬至', 19 => '小寒',
 958:  20 => '大寒', 21 => '立春', 22 => '雨水', 23 => '啓蟄'
 959: ),
 960: 'en' => array(
 961:   0 => 'Sprinf Equinox',
 962:   1 => 'Fresh Green',
 963:   2 => 'Grain Rain',
 964:   3 => 'Beginning of Summer',
 965:   4 => 'Lesser Fullness',
 966:   5 => 'Grain in Ear',
 967:   6 => 'Summer Solstice',
 968:   7 => 'Lesser Heat',
 969:   8 => 'Greater Heat',
 970:   9 => 'Beginning of Autumn',
 971:  10 => 'End of Heat',
 972:  11 => 'White Dew',
 973:  12 => 'Autumnal Equinox',
 974:  13 => 'Cold Dew',
 975:  14 => 'First Frost',
 976:  15 => 'Beginning of Winter',
 977:  16 => 'Light Snow',
 978:  17 => 'Heavy Snow',
 979:  18 => 'White Solstice',
 980:  19 => 'Lesser Cold',
 981:  20 => 'Greter Cold',
 982:  21 => 'Begining of Spring',
 983:  22 => 'Rain Water',
 984:  23 => 'Insects Awakening',
 985: ),
 986: 'en3' => array(
 987:   0 => 'Sprinf Equinox',
 988:   1 => 'Fresh Green',
 989:   2 => 'Grain Rain',
 990:   3 => 'Beginning of Summer',
 991:   4 => 'Lesser Fullness',
 992:   5 => 'Grain in Ear',
 993:   6 => 'Summer Solstice',
 994:   7 => 'Lesser Heat',
 995:   8 => 'Greater Heat',
 996:   9 => 'Beginning of Autumn',
 997:  10 => 'End of Heat',
 998:  11 => 'White Dew',
 999:  12 => 'Autumnal Equinox',
1000:  13 => 'Cold Dew',
1001:  14 => 'First Frost',
1002:  15 => 'Beginning of Winter',
1003:  16 => 'Light Snow',
1004:  17 => 'Heavy Snow',
1005:  18 => 'White Solstice',
1006:  19 => 'Lesser Cold',
1007:  20 => 'Greter Cold',
1008:  21 => 'Begining of Spring',
1009:  22 => 'Rain Water',
1010:  23 => 'Insects Awakening',
1011: ));
1012: 
1013:     //表示言語を設定する.
1014:     $lng = 'jp';        //デフォルトは日本語
1015:     foreach ($table as $key=>$arr) {
1016:         if (preg_match('/^' . $key . '$/i', $this->language> 0) {
1017:             $lng = $key;
1018:             break;
1019:         }
1020:     }
1021: 
1022:     //太陽黄経を計算する.
1023:     $l1 = $this->longitude_sun($year, $month, $day, 0, 0, 0);
1024:     $l2 = $this->longitude_sun($year, $month, $day, 24, 0, 0);
1025:     $n1 = floor($l1 / 15.0);
1026:     $n2 = floor($l2 / 15.0);
1027: 
1028:     return ($n1 !$n2? $table[$lng][$n2: '';
1029: }

年月日から二十四節気を求めるのが、ユーザー関数 getSolarTerm である。
直前の呼ばれた時の二十四節気をstatic変数 $old にn保持しておき、そこから視黄経が15度以上離れたら、新しい二十四節気を配列 $table から取り出して返す。

解説:七十二候の算出

1068: /**
1069:  * 指定した年月日の七十二候を求める.
1070:  * 七十二候でなければ空文字を返す.
1071:  * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-42-01.shtm
1072:  * @param   int $year, $month, $day  グレゴリオ暦による年月日
1073:  * @return  string 七十二候/'' :七十二候ではない
1074: */
1075: function getSolarTerm72($year, $month, $day) {
1076:     static $old = -1.0;
1077: //七十二候(参考)国立天文台暦計算室 https://eco.mtk.nao.ac.jp/koyomi/wiki/B5A8C0E12FBCB7BDBDC6F3B8F5.html 「宝暦暦以降」による
1078:     static $table = array(
1079:  0 => '雀始巣',
1080:  1 => '桜始開',
1081:  2 => '雷乃発声',
1082:  3 => '玄鳥至',
1083:  4 => '鴻雁北',
1084:  5 => '虹始見',
1085:  6 => '葭始生',
1086:  7 => '霜止出苗',
1087:  8 => '牡丹華',
1088:  9 => '蛙始鳴',
1089: 10 => '蚯蚓出',
1090: 11 => '竹笋生',
1091: 12 => '蚕起食桑',
1092: 13 => '紅花栄',
1093: 14 => '麦秋至',
1094: 15 => '蟷螂生',
1095: 16 => '腐草為蛍',
1096: 17 => '梅子黄',
1097: 18 => '乃東枯',
1098: 19 => '菖蒲華',
1099: 20 => '半夏生',
1100: 21 => '温風至',
1101: 22 => '蓮始開',
1102: 23 => '鷹乃学習',
1103: 24 => '桐始結花',
1104: 25 => '土潤溽暑',
1105: 26 => '大雨時行',
1106: 27 => '涼風至',
1107: 28 => '寒蝉鳴',
1108: 29 => '蒙霧升降',
1109: 30 => '綿柎開',
1110: 31 => '天地始粛',
1111: 32 => '禾乃登',
1112: 33 => '草露白',
1113: 34 => '鶺鴒鳴',
1114: 35 => '玄鳥去',
1115: 36 => '雷乃収声',
1116: 37 => '蟄虫坏戸',
1117: 38 => '水始涸',
1118: 39 => '鴻雁来',
1119: 40 => '菊花開',
1120: 41 => '蟋蟀在戸',
1121: 42 => '霜始降',
1122: 43 => '霎時施',
1123: 44 => '楓蔦黄',
1124: 45 => '山茶始開',
1125: 46 => '地始凍',
1126: 47 => '金盞香',
1127: 48 => '虹蔵不見',
1128: 49 => '朔風払葉',
1129: 50 => '橘始黄',
1130: 51 => '閉塞成冬',
1131: 52 => '熊蟄穴',
1132: 53 => '鱖魚群',
1133: 54 => '乃東生',
1134: 55 => '麋角解',
1135: 56 => '雪下出麦',
1136: 57 => '芹乃栄',
1137: 58 => '水泉動',
1138: 59 => '雉始雊',
1139: 60 => '款冬華',
1140: 61 => '水沢腹堅',
1141: 62 => '鶏始乳',
1142: 63 => '東風解凍',
1143: 64 => '黄鶯睍睆',
1144: 65 => '魚上氷',
1145: 66 => '土脉潤起',
1146: 67 => '霞始靆',
1147: 68 => '草木萌動',
1148: 69 => '蟄虫啓戸',
1149: 70 => '桃始笑',
1150: 71 => '菜虫化蝶'
1151: );
1152: 
1153:     //太陽黄経
1154:     $l1 = $this->longitude_sun($year, $month, $day, 0, 0, 0);
1155:     $l2 = $this->longitude_sun($year, $month, $day, 24, 0, 0);
1156: 
1157:     $n1 = floor($l1 / 5.0);
1158:     $n2 = floor($l2 / 5.0);
1159: 
1160:     return ($n1 !$n2? $table[$n2: '';
1161: }

同様に、年月日から七十二候を求めるのが、ユーザー関数 getSolarTerm72 である。
表記については、国立天文台暦計算室のもの(宝暦暦以降)を参考にした。

解説:節分かどうか

1163: /**
1164:  * 指定した年月日が節分(立春の前日)かどうかを求める.
1165:  * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-42-01.shtm#php_isSetsubun
1166:  * @param   int $year, $month, $day  グレゴリオ暦による年月日
1167:  * @return  bool TRUE:節分/FALSE:節分ではない
1168: */
1169: function isSetsubun($year, $month, $day) {
1170:     //太陽黄経
1171:     $l1 = $this->longitude_sun($year, $month, $day, +24, 0, 0);
1172:     $l2 = $this->longitude_sun($year, $month, $day, +48, 0, 0);
1173: 
1174:     $n1 = floor($l1 / 15.0);
1175:     $n2 = floor($l2 / 15.0);
1176: 
1177:     //翌日が立春かどうか
1178:     return (($n1 !$n2&& ($n2 == 21)) ? TRUE : FALSE;
1179: }

その日が節分かどうかを判定するのがメソッド isSetsubun である。
計算内容は二十四節気を求める getSolarTerm とほぼ同じで、翌日が立春かどうかを判定している。

活用例

みんなの知識 ちょっと便利帳では、「二十四節気・七十二候を計算する」「暑中見舞い・残暑見舞いを送る時期は?」「指定した年の節分を調べる」のコーナーで、このサンプル・プログラムを活用している。ありがとうございます。

参考書籍

表紙 日の出・日の入りの計算
著者 長沢工
出版社 地人書館
サイズ 単行本
発売日 1999年12月
価格 1,650円(税込)
ISBN 9784805206348
 

参考サイト

(この項おわり)
header