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

サンプル・プログラム
getMoonAge.php | サンプル・プログラム本体。 |
pahooCalendar.php | 暦計算クラス pahooCalendar。 暦計算クラスの使い方は「PHPで日出没・月出没・月齢・潮を計算」を参照。include_path が通ったディレクトリに配置すること。 |
準備:外部クラスなど
0036: //指定できる西暦年の範囲
0037: define('MIN_YEAR', 1948);
0038: define('MAX_YEAR', 2099);
0039:
0040: //計算期間(月)
0041: define('CALC_TERM', 3);
0042:
0043: //世界時からの時差
0044: define('UTCDIFF', 9);
0045:
0046: //表示幅(単位:ピクセル)
0047: define('WIDTH', 550);
0048:
0049: //暦計算クラス
0050: require_once('pahooCalendar.php');

月齢、月の視半径、各種カレンダー計算は、ユーザークラス "pahooCalendar" に用意したメソッド群を利用する。
そこで、クラスファイル "pahooCalendar.php" を require_once し、オブジェクトを生成する。
解説:月の視黄経の算出

0763: /**
0764: * 月の黄経計算(視黄経)
0765: * @param double $jy 2000.0からの経過年数
0766: * @return double月の黄経(視黄経)
0767: */
0768: function __longitude_moon($jy) {
0769: $am = 0.0006 * sin(deg2rad($this->__angle( 54.0 + 19.3 * $jy)));
0770: $am += 0.0006 * sin(deg2rad($this->__angle( 71.0 + 0.2 * $jy)));
0771: $am += 0.0020 * sin(deg2rad($this->__angle( 55.0 + 19.34 * $jy)));
0772: $am += 0.0040 * sin(deg2rad($this->__angle(119.5 + 1.33 * $jy)));
0773: $rm_moon = 0.0003 * sin(deg2rad($this->__angle(280.0 + 23221.3 * $jy)));
0774: $rm_moon += 0.0003 * sin(deg2rad($this->__angle(161.0 + 40.7 * $jy)));
0775: $rm_moon += 0.0003 * sin(deg2rad($this->__angle(311.0 + 5492.0 * $jy)));
0776: $rm_moon += 0.0003 * sin(deg2rad($this->__angle(147.0 + 18089.3 * $jy)));
0777: $rm_moon += 0.0003 * sin(deg2rad($this->__angle( 66.0 + 3494.7 * $jy)));
0778: $rm_moon += 0.0003 * sin(deg2rad($this->__angle( 83.0 + 3814.0 * $jy)));
0779: $rm_moon += 0.0004 * sin(deg2rad($this->__angle( 20.0 + 720.0 * $jy)));
0780: $rm_moon += 0.0004 * sin(deg2rad($this->__angle( 71.0 + 9584.7 * $jy)));
0781: $rm_moon += 0.0004 * sin(deg2rad($this->__angle(278.0 + 120.1 * $jy)));
0782: $rm_moon += 0.0004 * sin(deg2rad($this->__angle(313.0 + 398.7 * $jy)));
0783: $rm_moon += 0.0005 * sin(deg2rad($this->__angle(332.0 + 5091.3 * $jy)));
0784: $rm_moon += 0.0005 * sin(deg2rad($this->__angle(114.0 + 17450.7 * $jy)));
0785: $rm_moon += 0.0005 * sin(deg2rad($this->__angle(181.0 + 19088.0 * $jy)));
0786: $rm_moon += 0.0005 * sin(deg2rad($this->__angle(247.0 + 22582.7 * $jy)));
0787: $rm_moon += 0.0006 * sin(deg2rad($this->__angle(128.0 + 1118.7 * $jy)));
0788: $rm_moon += 0.0007 * sin(deg2rad($this->__angle(216.0 + 278.6 * $jy)));
0789: $rm_moon += 0.0007 * sin(deg2rad($this->__angle(275.0 + 4853.3 * $jy)));
0790: $rm_moon += 0.0007 * sin(deg2rad($this->__angle(140.0 + 4052.0 * $jy)));
0791: $rm_moon += 0.0008 * sin(deg2rad($this->__angle(204.0 + 7906.7 * $jy)));
0792: $rm_moon += 0.0008 * sin(deg2rad($this->__angle(188.0 + 14037.3 * $jy)));
0793: $rm_moon += 0.0009 * sin(deg2rad($this->__angle(218.0 + 8586.0 * $jy)));
0794: $rm_moon += 0.0011 * sin(deg2rad($this->__angle(276.5 + 19208.02 * $jy)));
0795: $rm_moon += 0.0012 * sin(deg2rad($this->__angle(339.0 + 12678.71 * $jy)));
0796: $rm_moon += 0.0016 * sin(deg2rad($this->__angle(242.2 + 18569.38 * $jy)));
0797: $rm_moon += 0.0018 * sin(deg2rad($this->__angle( 4.1 + 4013.29 * $jy)));
0798: $rm_moon += 0.0020 * sin(deg2rad($this->__angle( 55.0 + 19.34 * $jy)));
0799: $rm_moon += 0.0021 * sin(deg2rad($this->__angle(105.6 + 3413.37 * $jy)));
0800: $rm_moon += 0.0021 * sin(deg2rad($this->__angle(175.1 + 719.98 * $jy)));
0801: $rm_moon += 0.0021 * sin(deg2rad($this->__angle( 87.5 + 9903.97 * $jy)));
0802: $rm_moon += 0.0022 * sin(deg2rad($this->__angle(240.6 + 8185.36 * $jy)));
0803: $rm_moon += 0.0024 * sin(deg2rad($this->__angle(252.8 + 9224.66 * $jy)));
0804: $rm_moon += 0.0024 * sin(deg2rad($this->__angle(211.9 + 988.63 * $jy)));
0805: $rm_moon += 0.0026 * sin(deg2rad($this->__angle(107.2 + 13797.39 * $jy)));
0806: $rm_moon += 0.0027 * sin(deg2rad($this->__angle(272.5 + 9183.99 * $jy)));
0807: $rm_moon += 0.0037 * sin(deg2rad($this->__angle(349.1 + 5410.62 * $jy)));
0808: $rm_moon += 0.0039 * sin(deg2rad($this->__angle(111.3 + 17810.68 * $jy)));
0809: $rm_moon += 0.0040 * sin(deg2rad($this->__angle(119.5 + 1.33 * $jy)));
0810: $rm_moon += 0.0040 * sin(deg2rad($this->__angle(145.6 + 18449.32 * $jy)));
0811: $rm_moon += 0.0040 * sin(deg2rad($this->__angle( 13.2 + 13317.34 * $jy)));
0812: $rm_moon += 0.0048 * sin(deg2rad($this->__angle(235.0 + 19.34 * $jy)));
0813: $rm_moon += 0.0050 * sin(deg2rad($this->__angle(295.4 + 4812.66 * $jy)));
0814: $rm_moon += 0.0052 * sin(deg2rad($this->__angle(197.2 + 319.32 * $jy)));
0815: $rm_moon += 0.0068 * sin(deg2rad($this->__angle( 53.2 + 9265.33 * $jy)));
0816: $rm_moon += 0.0079 * sin(deg2rad($this->__angle(278.2 + 4493.34 * $jy)));
0817: $rm_moon += 0.0085 * sin(deg2rad($this->__angle(201.5 + 8266.71 * $jy)));
0818: $rm_moon += 0.0100 * sin(deg2rad($this->__angle( 44.89 + 14315.966 * $jy)));
0819: $rm_moon += 0.0107 * sin(deg2rad($this->__angle(336.44 + 13038.696 * $jy)));
0820: $rm_moon += 0.0110 * sin(deg2rad($this->__angle(231.59 + 4892.052 * $jy)));
0821: $rm_moon += 0.0125 * sin(deg2rad($this->__angle(141.51 + 14436.029 * $jy)));
0822: $rm_moon += 0.0153 * sin(deg2rad($this->__angle(130.84 + 758.698 * $jy)));
0823: $rm_moon += 0.0305 * sin(deg2rad($this->__angle(312.49 + 5131.979 * $jy)));
0824: $rm_moon += 0.0348 * sin(deg2rad($this->__angle(117.84 + 4452.671 * $jy)));
0825: $rm_moon += 0.0410 * sin(deg2rad($this->__angle(137.43 + 4411.998 * $jy)));
0826: $rm_moon += 0.0459 * sin(deg2rad($this->__angle(238.18 + 8545.352 * $jy)));
0827: $rm_moon += 0.0533 * sin(deg2rad($this->__angle( 10.66 + 13677.331 * $jy)));
0828: $rm_moon += 0.0572 * sin(deg2rad($this->__angle(103.21 + 3773.363 * $jy)));
0829: $rm_moon += 0.0588 * sin(deg2rad($this->__angle(214.22 + 638.635 * $jy)));
0830: $rm_moon += 0.1143 * sin(deg2rad($this->__angle( 6.546 + 9664.0404 * $jy)));
0831: $rm_moon += 0.1856 * sin(deg2rad($this->__angle(177.525 + 359.9905 * $jy)));
0832: $rm_moon += 0.2136 * sin(deg2rad($this->__angle(269.926 + 9543.9773 * $jy)));
0833: $rm_moon += 0.6583 * sin(deg2rad($this->__angle(235.700 + 8905.3422 * $jy)));
0834: $rm_moon += 1.2740 * sin(deg2rad($this->__angle(100.738 + 4133.3536 * $jy)));
0835: $rm_moon += 6.2887 * sin(deg2rad($this->__angle(134.961 + 4771.9886 * $jy + $am)));
0836:
0837: return $rm_moon + $this->__angle(218.3161 + 4812.67881 * $jy);
0838: }
0840: /**
0841: * 月の黄経計算(視黄経)
0842: * @param int $year, $month, $day グレゴリオ暦による年月日
0843: * @param double $hour, $min, $sec時分秒(世界時)
0844: * @return double月の黄経(視黄経)
0845: */
0846: function longitude_moon($year, $month, $day, $hour, $min, $sec) {
0847: $jy = $this->Gregorian2JY($year, $month, $day, $hour, $min, $sec);
0848:
0849: return $this->__longitude_moon($jy);
0850: }
解説:月齢の算出
1081: /**
1082: * 月齢を求める(視黄経)
1083: * @param int $year, $month, $day グレゴリオ暦による年月日
1084: * @param double $hour, $min, $sec時分秒(世界時)
1085: * @return double月齢(視黄経)
1086: */
1087: function moon_age($year, $month, $day, $hour, $min, $sec) {
1088: $jd0 = $this->Gregorian2JD($year, $month, $day, $hour, $min, $sec) + ($this->TDIFF / 24);
1089: $tm1 = floor($jd0);
1090: $tm2 = $jd0 - $tm1;
1091:
1092: //繰り返し計算によって朔の時刻を計算
1093: //誤差が±1.0 sec以内になったら打ち切る
1094: $lc = 1;
1095: $delta_t1 = 0;
1096: $delta_t2 = 1;
1097: while (($delta_t1 + abs($delta_t2)) > (1.0 / 86400.0)) {
1098: $jd = $tm1 + $tm2;
1099: list($year, $month, $day, $hour, $min, $sec) = $this->JD2Gregorian($jd);
1100: $longitude_sun = $this->longitude_sun($year, $month, $day, $hour, $min, $sec);
1101: $longitude_moon = $this->longitude_moon($year, $month, $day, $hour, $min, $sec);
1102:
1103: //Δλ=λmoon-λsun
1104: $delta_rm = $longitude_moon - $longitude_sun;
1105:
1106: //ループ1回目 で $delta_rm < 0.0の場合には引き込み範囲に入るよう補正
1107: if ($lc == 1 && $delta_rm < 0) {
1108: $delta_rm = $this->__angle($delta_rm);
1109: //春分の近くで朔がある場合 ( 0 ≦λsun≦ 20 ) で、月の黄経λmoon≧300の
1110: //場合には、Δλ= 360.0 - Δλ と計算して補正
1111: } else if ($longitude_sun >= 0 && $longitude_sun <= 20 && $longitude_moon >= 300) {
1112: $delta_rm = $this->__angle($delta_rm);
1113: $delta_rm = 360 - $delta_rm;
1114: //Δλの引き込み範囲 ( ±40°) を逸脱した場合には補正
1115: } else if (abs($delta_rm) > 40.0) {
1116: $delta_rm = $this->__angle($delta_rm);
1117: }
1118:
1119: //時刻引数の補正値 Δt
1120: $delta_t1 = floor($delta_rm * 29.530589 / 360.0);
1121: $delta_t2 = $delta_rm * 29.530589 / 360.0;
1122: $delta_t2 -= $delta_t1;
1123:
1124: //時刻引数の補正
1125: $tm1 = $tm1 - $delta_t1;
1126: $tm2 = $tm2 - $delta_t2;
1127: if ($tm2 < 0) {
1128: $tm2++;
1129: $tm1--;
1130: }
1131:
1132: //ループ回数が15回になったら、初期値tmをtm-26
1133: if ($lc == 15 && abs($delta_t1 + $delta_t2) > (1.0 / 86400.0)) {
1134: $tm1 = floor($jd0 - 26);
1135: $tm2 = 0;
1136: //初期値を補正したにも関わらず振動を続ける場合は、
1137: //初期値を答えとして返して強制的にループを抜け出して異常終了
1138: } else if ($lc > 30 && abs($delta_t1 + $delta_t2) > (1.0 / 86400.0)) {
1139: $tm1 = $jd0;
1140: $tm2 = 0;
1141: break;
1142: }
1143: $lc++;
1144: }
1145:
1146: //時刻引数を合成
1147: $ma = $jd0 - ($tm2 + $tm1);
1148: if ($ma > 30) $ma -= 30;
1149: return $ma;
1150: }
ここから、月齢を求めるためには、「PHPで二十四節気一覧を作成」で紹介した太陽の視黄経と、今回作成した 月の視黄経の差分を計算することにする。

Wikipedia には月齢を求める簡易式が掲載されているが、それより今回のプログラムの方が正確である。
活用例
参考サイト
- PHPでスーパームーンを計算する:ぱふぅ家のホームページ
- PHPで二十四節気一覧を作成:ぱふぅ家のホームページ
- 月齢=今日の月・現在の月=:みんなの知識 ちょっと便利帳
- こよみ用語解説 二十四節気:国立天文台暦計算室
- CalcMoonage:GitHub
- Ruby - 月齢計算!:mk-mode BLOG
月齢は、太陽と月の位置関係から計算できる。今回は、PHPで月の視黄経を算出するプログラムを作り、指定した月から3ヶ月分の月齢一覧を求めることを目標にする。
(2021年5月8日)PHP8対応,リファラ・チェック改良