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

サンプル・プログラム
supermoon.php | サンプル・プログラム本体。 |
pahooCalendar.php | 暦・潮位計算クラス pahooCalendar。 暦・潮位計算クラスの使い方は「PHPで二十四節気・七十二候一覧を作成」「PHPで月齢を計算」「PHPで日出没・月出没・月齢・潮を計算」「PHPで潮位を計算する」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
バージョン | 更新日 | 内容 |
---|---|---|
1.5.0 | 2023/01/14 | 数値入力にSpinner、pahooInputData導入 |
1.4.0 | 2023/01/09 | pahooCalendarクラスの計算精度を向上 |
1.3.0 | 2021/01/04 | 満月の日を取得するアルゴリズムを見直した |
1.2 | 2021/01/04 | PHP8対応,満月の呼び名等を追加 |
1.1 | 2018/01/03 | 明るさの比などを一覧表示 |
バージョン | 更新日 | 内容 |
---|---|---|
4.5.1 | 2025/05/31 | deg2ddmm(), deg2hhmm() 不具合修正 |
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() 表記改訂:水澤腹堅→水沢腹堅 |
バージョン | 更新日 | 内容 |
---|---|---|
1.8.1 | 2025/03/15 | validRegexPattern() -- debug |
1.8.0 | 2024/11/12 | validRegexPattern() 追加 |
1.7.0 | 2024/10/09 | validURL() validEmail() 追加 |
1.6.0 | 2024/10/07 | isButton() -- buttonタグに対応 |
1.5.0 | 2024/01/28 | exitIfExceedVersion() 追加 |
準備:初期値など
supermoon.php
36: //指定できる西暦年の範囲
37: define('MIN_YEAR', 1901);
38: define('MAX_YEAR', 2099);
39:
40: //表示言語(jp:日本語, en:英語, en3:英語略記)
41: define('LANGUAGE', 'jp');
42:
43: //世界時からの時差(日本標準時)
44: define('UTCDIFF', +9.0);
45:
46: //計算期間(月)
47: define('CALC_TERM', 12);
48:
49: //視半径が最小/最大の時の背景色
50: define('MIN_COLOR', '88EEFF');
51: define('MAX_COLOR', 'FFEE88');
52:
53: //Spinner - jQuery UI を使用するかどうか
54: define('USESPINNER', TRUE);
55:
56: //数値増減クリックで即判定するかどうか(TRUE:即判定,FALE:判定ボタンを用意)
57: define('ONCHANGE', FALSE);
58:
59: //表示幅(単位:ピクセル)
60: define('WIDTH', 600);
61:
62: //require_once()で呼ぶファイルはinclude_pathが通っているフォルダに配置すること。
63: //暦計算クラス
64: require_once('pahooCalendar.php');
65:
66: //データ入力に関わる関数群
67: require_once('pahooInputData.php');

月齢、月の視半径、各種カレンダー計算は、ユーザークラス "pahooCalendar" に用意したメソッド群を利用する。
オブジェクト生成時に、表示言語として "ja"(日本語)を、世界時との時差としてユーザー定義の定数 UTCDIFF を渡しておく。こうすることで、pahooCalendar クラスが出力する文字列は日本語に、日時計算は時差 UTCDIFF がある前提で計算を行う。

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

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

一方、月齢は朔の日(新月の日)を第1日とする日数であるから、月齢15が必ずしも満月の日になるとは限らない。
pahooCalendar.php
1898: /**
1899: * 指定した日時の次の満月の日時を求める(日時はローカル時間).
1900: * 太陽と月の黄緯差180度になる日時を近似計算で求める.
1901: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-50-01.shtm
1902: * @param int $year, $month, $day 年月日(グレゴリオ暦)
1903: * @param float $hour, $min, $sec 時分秒(ローカル時間)
1904: * @param float $tdiff UTCとの時差;NULLの時はTDIFF参照
1905: * @return array($year, $month, $day, $hour, $min, $sec) 日時(ローカル時間)
1906: */
1907: function next_fullmoon($year, $month, $day, $hour, $min, $sec, $tdiff=NULL) {
1908: $dif = 29.55; //一朔望月(近似計算の指標)
1909: $jd = $this->Gregorian2JD($year, $month, $day, $hour, $min, $sec, $tdiff);
1910: $jdc = (float)$jd;
1911:
1912: //ニュートン法による近似計算
1913: for ($i = 1; $i < 25; $i++) {
1914: list($year, $month, $day, $hour, $min, $sec) = $this->JD2Gregorian($jdc, $tdiff);
1915: $ym = $this->longitude_moon($year, $month, $day, $hour, $min, $sec, $tdiff);
1916: $ys = $this->longitude_sun($year, $month, $day, $hour, $min, $sec, $tdiff);
1917:
1918: //太陽と月の黄緯差180度を目指す.
1919: $dy = $ym - $ys - 180.0;
1920:
1921: //引き込み範囲に入ったら補正する.
1922: if ($dy <= -360.0) {
1923: $dy += 360.0;
1924: } else if ($dy >= 0.0) {
1925: $dy -= 360.0;
1926: }
1927:
1928: //誤差内に入ったらループを脱出する.
1929: if ($dy >= 0.0 && $dy <= 0.0001) break;
1930: if ($dy < -0.0 && $dy >= -0.0001) break;
1931:
1932: $dd = $dy / $dif;
1933: $jdc -= $dd;
1934: }
1935:
1936: return array($year, $month, $day, $hour, $min, $sec);
1937: }
太陽の視黄経の計算メソッド longitude_sun と月の視黄経の計算メソッド longitude_moon はすでに説明したとおりだが、黄経値から年月日を計算する逆関数は存在しないため、近似計算によって求めている。このため、国立天文台が発表する時刻と数分のズレがある。
解説:月の視半径を求める
pahooCalendar.php
1711: /**
1712: * J2000.0からの経過年数における月の視差(度)を求める。
1713: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-44-01.shtm
1714: * @param float $jy 2000.0からの経過年数
1715: * @return float 月の視差(度)
1716: */
1717: function __dif_moon($jy) {
1718: $p_moon = 0.0003 * sin(deg2rad($this->__angle(227.0 + 4412.0 * $jy)));
1719: $p_moon += 0.0004 * sin(deg2rad($this->__angle(194.0 + 3773.4 * $jy)));
1720: $p_moon += 0.0005 * sin(deg2rad($this->__angle(329.0 + 8545.4 * $jy)));
1721: $p_moon += 0.0009 * sin(deg2rad($this->__angle(100.0 + 13677.3 * $jy)));
1722: $p_moon += 0.0028 * sin(deg2rad($this->__angle( 0.0 + 9543.98 * $jy)));
1723: $p_moon += 0.0078 * sin(deg2rad($this->__angle(325.7 + 8905.34 * $jy)));
1724: $p_moon += 0.0095 * sin(deg2rad($this->__angle(190.7 + 4133.35 * $jy)));
1725: $p_moon += 0.0518 * sin(deg2rad($this->__angle(224.98 + 4771.989 * $jy)));
1726: $p_moon += 0.9507 * sin(deg2rad($this->__angle(90.0)));
1727:
1728: return $p_moon;
1729: }
pahooCalendar.php
1731: /**
1732: * 指定した日時における月の視差(度)を求める(日時はローカル時間)。
1733: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-44-01.shtm
1734: * @param int $year, $month, $day グレゴリオ暦による年月日
1735: * @param float $hour, $min, $sec 時分秒(ローカル時間)
1736: * @param float $tdiff UTCとの時差;NULLの時はTDIFF
1737: * @return float 月の視差
1738: */
1739: function dif_moon($year, $month, $day, $hour, $min, $sec, $tdiff=NULL) {
1740: $jy = $this->Gregorian2JY($year, $month, $day, $hour, $min, $sec, $tdiff);
1741:
1742: return $this->__dif_moon($jy);
1743: }
pahooCalendar.php
1745: /**
1746: * 指定した日時における月の視半径(度)を求める(日時はローカル時間)。
1747: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-50-01.shtm
1748: * @param int $year, $month, $day グレゴリオ暦による年月日
1749: * @param float $hour, $min, $sec 時分秒(ローカル時間)
1750: * @param float $tdiff UTCとの時差;NULLの時はTDIFF
1751: * @return float 月の視半径(度)
1752: */
1753: function rad_moon($year, $month, $day, $hour, $min, $sec, $tdiff=NULL) {
1754: $dif = $this->dif_moon($year, $month, $day, $hour, $min, $sec, $tdiff);
1755: $rad = asin(0.2725 * sin(deg2rad($dif)));
1756:
1757: return rad2deg($rad);
1758: }
これを rad_moon として実装している。
$$ rad = sin^{-1}(0.2725 \times sin(dif)) $$
解説:ある期間に起きる満月と視半径を計算
supermoon.php
201: /**
202: * ある期間に起きる満月と視半径を計算
203: * @param int $year 開始年(西暦)
204: * @param int $month 開始月
205: * @param int $term 計算期間(月)
206: * @param array $items 計算結果を格納する配列
207: * @return int 満月の回数
208: */
209: function calcSuperMoon($year, $month, $term, &$items) {
210: //暦計算に関わるクラス
211: $pcl = new pahooCalendar(LANGUAGE, UTCDIFF);
212:
213: $i = $cnt = 0;
214: $day = 1;
215: while ($i < $term) {
216: //次の満月の日時を求める
217: list($year1, $month1, $day1, $hour1, $min1, $sec1) =$pcl->next_fullmoon($year, $month, $day, 0, 0, 0);
218: $items[$cnt]['year'] = $year1;
219: $items[$cnt]['month'] = $month1;
220: $items[$cnt]['day'] = $day1;
221: $items[$cnt]['week'] = $pcl->getWeekString($year1, $month1, $day1);
222: $items[$cnt]['hour'] = $hour1;
223: $items[$cnt]['min'] = $min1 + round($sec1 / 60.0, 0);
224: //月の視半径
225: $items[$cnt]['rad'] = $pcl->rad_moon($year1, $month1, $day1, $hour1, $min1, $sec1);
226: //満月の呼び名
227: $items[$cnt]['name'] = $pcl->getFullMoonNickname($month1);
228: //次のパラメータを用意する
229: $cnt++;
230: $year = $year1;
231: if ($month < $month1) $i++;
232: $month = $month1;
233: $day = $day1 + 20.0; //次の計算基準は26日後
234: if ($day > $pcl->getDaysInMonth($year, $month)) {
235: $day = 1;
236: $month++;
237: $i++;
238: if ($month > 12) {
239: $month = 1;
240: $year++;
241: }
242: }
243: }
244: //オブジェクト解放
245: $pcl = NULL;
246:
247: return $cnt;
248: }
解説:満月の呼び名
pahooCalendar.php
1979: /**
1980: * 指定した月の満月の呼び名を求める.
1981: * 参考サイト https://www.pahoo.org/e-soul/webtech/php02/php02-50-01.shtm
1982: * @param int $month 月
1983: * @return string 満月の呼び名
1984: */
1985: function getFullMoonNickname($month) {
1986: $table_jp = array(
1987: 'ウルフムーン',
1988: 'スノームーン',
1989: 'ワームムーン',
1990: 'ピンクムーン',
1991: 'フラワームーン',
1992: 'ストロベリームーン',
1993: 'バックムーン', //または「バクムーン」.発音はbʌkだが,buckskinをバックスキンと読むことから,ここでは「バクムーン」にした.
1994: 'スタージョンムーン', //または「スタージャンムーン」.Twitterでアンケートをとて「スタージョンムーン」にした. https://twitter.com/papa_pahoo/status/1620259072871395328
1995: 'ハーベストムーン',
1996: 'ハンターズムーン',
1997: 'ビーバームーン',
1998: 'コールドムーン'
1999: );
2000:
2001: $table_en = array(
2002: 'Wolf Moon',
2003: 'Snow Moon',
2004: 'Worm Moon',
2005: 'Pink Moon',
2006: 'Flower Moon',
2007: 'Strawberry Moon',
2008: 'Buck Moon',
2009: 'Sturgeon Moon',
2010: 'Harvest Moon',
2011: 'Hunter\#x27;s Moon',
2012: 'Beaver Moon',
2013: 'Cold Moon'
2014: );
2015:
2016: $month = (int)$month;
2017: if (($month >= 1) && ($month << 12)) {
2018: if ($this->language == 'jp') {
2019: $name = $table_jp[$month - 1];
2020: } else {
2021: $name = $table_en[$month - 1];
2022: }
2023: } else {
2024: $name = '';
2025: }
2026:
2027: return $name;
2028: }

7月の Buck Moon の buk(雄ジカ)は発音はbʌkだが、buckskinをバックスキンと読むことから、ここでは「バクムーン」にした。
8月の Sturgeon Moon の sturgeon(チョウザメ)の発音はstɚːdʒənだが、Wikipedia日本語版にある Sturgeon をもつ人名の表記は揺れている。
- ウィリアム・スタージャン - イギリスの物理学者。
- シオドア・スタージョン - アメリカのSF作家。
- ニコラ・スタージョン - スコットランドの政治家。
- ローリン・S・スタージョン - アメリカの映画監督
8月の満月「スタージャンムーン」のカタカナ表記を見直そうかどうか迷っています。
— パパぱふぅ@𝙥𝙖𝙝𝙤𝙤.𝙤𝙧𝙜 (@papa_pahoo) 2023年1月31日
英語表記 Sturgeon Moon
Sturgeonは「チョウザメ」。
よろしければアンケートにご回答ください。
解説:一覧表作成
supermoon.php
251: /**
252: * 満月一覧から表示用HTMLを求める.
253: * @param array $items 計算結果
254: * @return string HTML文字列
255: */
256: function makeTable($items) {
257: //最大・最小の視半径を求める
258: $minrad = 999;
259: $minid = -1;
260: $maxrad = 0;
261: $maxid = -1;
262: foreach ($items as $key=>$item) {
263: if ($item['rad'] < $minrad) {
264: $minrad = $item['rad'];
265: $minid = $key;
266: }
267: if ($item['rad'] > $maxrad) {
268: $maxrad = $item['rad'];
269: $maxid = $key;
270: }
271: }
272:
273: //一覧表作成
274: $width = WIDTH;
275: $outstr =<<< EOT
276: <table style="width:{$width};">
277: <tr><th>年月日・時</th><th colspan="2">月の視半径<br /><span class="comp">(最小半径を100%)</span></th><th>明るさの比<br /><span class="comp">(最小半径を100%)</span></th><th>呼び名</th></tr>
278:
279: EOT;
280: foreach ($items as $key=>$item) {
281: $ymd = sprintf("%04d年%02d月%02d日(%s) %02d:%02d",
282: $item['year'], $item['month'], $item['day'], $item['week'], $item['hour'], $item['min']);
283: $mm = intval($item['rad'] * 60);
284: $s1 = intval(($item['rad'] * 60 - $mm) * 60);
285: $s2 = ($item['rad'] * 60 - $mm - $s1 / 60) * 60 * 100;
286: $rad = sprintf("%2d'%02d\".%02d", $mm, $s1, $s2);
287: $rat = sprintf("%3.1f", $item['rad'] / $minrad * 100);
288: $brg = sprintf("%3.1f", pow($item['rad'] / $minrad, 2) * 100);
289:
290: //背景色
291: if ($key == $minid) {
292: $color = ' style="background-color:#' . MIN_COLOR . ';"';
293: } else if ($key == $maxid) {
294: $color = ' style="background-color:#' . MAX_COLOR . ';"';
295: } else {
296: $color = '';
297: }
298:
299: $outstr .=<<< EOT
300: <tr{$color}>
301: <td>{$ymd}</td>
302: <td>{$rad}</td>
303: <td>{$rat}%</td>
304: <td>{$brg}%</td>
305: <td>{$item['name']}</td>
306: </tr>
307:
308: EOT;
309: }
310: $outstr .=<<< EOT
311: </table>
312: </body>
313:
314: EOT;
315:
316: return $outstr;
317: }

冒頭で、期間中の最小半径を求める。
これを基準に、視半径の比率、明るさの比率(半径の2乗)を計算し、一覧表にしてゆく。
活用例
参考サイト
- PHPで月齢を計算:ぱふぅ家のホームページ
- PHPで二十四節気・七十二候一覧を作成:ぱふぅ家のホームページ
- スーパームーン;AstroArts
- 「スーパームーン」ってなに?:国立天文台
- 暦Wiki/月の満ち欠け/月齢と満ち欠け]:国立天文台暦計算室
- 明日はスーパームーン:鹿角平天文台通信
- スーパームーンを調べる:みんなの知識 ちょっと便利帳
「PHPで月齢を計算」で月齢を求めるプログラムを作ったが、今回は満月の時の月の大きさ(視半径)を計算するプログラムを作ってみることにする。
(2023年2月3日)表記改訂:バクムーン→バックムーン,スタージャンムーン→スタージョンムーン
(2023年1月14日)数値入力にSpinner、pahooInputDataを導入した。
(2022年12月26日)満月の日を取得するアルゴリズムを見直した。