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

サンプル・プログラム
planetPhenomena.php | サンプル・プログラム本体 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooAstronomy.php | 天文計算クラス pahooAstronomy。 使い方は「PHPでホロスコープを描く」などを参照。include_path が通ったディレクトリに配置すること。 |
pahooCalendar.php | 暦計算クラス pahooCalendar。 暦計算クラスの使い方は「PHPで日出没・月出没・月齢・潮を計算」を参照。include_path が通ったディレクトリに配置すること。 |
バージョン | 更新日 | 内容 |
---|---|---|
1.0.0 | 2025/05/31 | 初版 |
バージョン | 更新日 | 内容 |
---|---|---|
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() 追加 |
バージョン | 更新日 | 内容 |
---|---|---|
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() 表記改訂:水澤腹堅→水沢腹堅 |
バージョン | 更新日 | 内容 |
---|---|---|
2.1.0 | 2025/06/01 | euatorialCoordinate() を追加 |
2.0.0 | 2025/05/31 | 全面改訂, 天象を計算できるようにした. |
1.0 | 2019/03/23 | 初版 |
準備:定数
planetPhenomena.php
58: // 初期値(START) =============================================================
59:
60: // 指定できる西暦年の範囲
61: define('MIN_YEAR', 1901);
62: define('MAX_YEAR', 2099);
63:
64: // 表示言語(jp:日本語, en:英語, en3:英語略記)
65: define('LANGUAGE', 'jp');
66:
67: // 世界時からの時差(日本標準時)
68: define('UTCDIFF', +9.0);
69:
70: // Spinner - jQuery UI を使用するかどうか
71: define('USESPINNER', TRUE);
72:
73: // 数値増減クリックで即判定するかどうか(TRUE:即判定,FALE:判定ボタンを用意)
74: define('ONCHANGE', FALSE);
75:
76: // 表示幅(単位:ピクセル)
77: define('WIDTH', 550);
78:
79: // 初期値(END) ===============================================================
準備:pahooAstronomy クラス
pahooAstronomy.php
11: require_once('pahooCalendar.php');
12:
13: // pahooAstronomyクラス ======================================================
14: class pahooAstronomy extends pahooCalendar {
惑星の天象


内合‥‥内惑星が地球と太陽の間にある。惑星は太陽に近く、観測しにくい。離角0度。
外合‥‥内惑星が太陽の向こう側にある。惑星は太陽に近く、観測しにくい。離角0度。
東方最大離角‥‥内惑星が太陽の東側にあり、日没後の西の空に見える最大の角距離のとき。
西方最大離角‥‥内惑星が太陽の西側にあり、日の出前の東の空に見える最大の角距離のとき。

合‥‥外惑星が太陽の向こう側にある。惑星は太陽に近く、観測しにくい。離角0度。
衝‥‥外惑星が地球と太陽の反対側にある。惑星は最も明るくなり、一晩中観測できる。離角180度。
東矩‥‥外惑星が太陽の東側90度の位置にあるとき。惑星は日没後に南の空に見える。離角+90度。
西矩‥‥
外惑星が太陽の西側90度の位置にあるとき。惑星は日の出前の東の空に見える。離角-90度。
解説:惑星の地心座標を求める
pahooAstronomy.php
306: /**
307: * 惑星の離角を求める.
308: * @param string $planet 惑星名(Mercury, Venus, ... Pluto)
309: * @param int $year, $month, $day グレゴリオ暦による年月日
310: * @param double $hour, $min, $sec 時分秒(地方時)
311: * @return double 離角(正数:太陽の東側,負数:太陽の西側)
312: */
313: function elongation($planet, $year, $month, $day, $hour, $min, $sec) {
314: $lngS = $this->longitude_sun($year, $month, $day, $hour, $min, $sec, $this->TDIFF);
315: list($lngE, $latE, $radE) = $this->zodiacEarthAP($planet, $year, $month, $day, $hour, $min, $sec);
316:
317: // 離角を求める.
318: $el = fmod($lngE - $lngS + 180.0, 360.0);
319: if ($el < 0) {
320: $el += 360.0;
321: }
322:
323: return $el - 180.0;
324: }
ここで求めた惑星の日心黄経を \( \lambda_s \)、地心黄経を \( \lambda_e \) とすると、惑星の離角は
\[ E = \lambda_s - \lambda_e \]
で求めることができる。
これを実装したメソッドが elongation である。
解説:内惑星の天象を求める
pahooAstronomy.php
365: /**
366: * 指定した年の内惑星の天象を求める.
367: * 内惑星:外合, 内合, 東方最大離角, 西方最大離角
368: * @param string $planet 惑星名(Mercury, Venus, ... Pluto)
369: * @param int $year 求めたい西暦年
370: * @param array $cals 暦を格納する配列
371: * [年][月][日] = 天象
372: * @return int 格納した天象の数
373: */
374: function planetPhenomenaInner($planet, $year, &$cals) {
375: $cnt = 0; // 格納した天象の数
376: $flag = 0; // +:西方最大離角後,-:東方最大離角後
377: $flagTom = FALSE; // 留フラグ
378:
379: // 指定年の前日(大晦日)から計算開始する.
380: $yy = $year - 1;
381: $mm = 12;
382: $dd = 31;
383: $e0 = $emin = $emax = $this->elongation($planet, $yy, $mm, $dd, 0, 0, 0);
384: $yy++;
385: $mm = 1;
386: do {
387: // 1ヶ月分のループ
388: $dayOfMonth = $this->getDaysInMonth($yy, $mm);
389: for ($dd = 1; $dd <= $dayOfMonth; $dd++) {
390: $e = $this->elongation($planet, $yy, $mm, $dd, 0, 0, 0);
391: // 外合
392: if (($e0 <= 0.0) && ($e >= 0.0)) {
393: for ($hh = -47; $hh < 0; $hh++) {
394: $e = $this->elongation($planet, $yy, $mm, $dd, $hh, 0, 0);
395: if (($e0 <= 0.0) && ($e >= 0.0)) {
396: $cals[$yy][$mm][$dd + floor(($hh - 1) / 24)] = '外合';
397: $cnt++;
398: $e0 = $e;
399: break;
400: } else {
401: $e0 = $e;
402: }
403: }
404: // 内合
405: } else if (($e0 >= 0.0) && ($e <= 0.0)) {
406: for ($hh = -47; $hh < 0; $hh++) {
407: $e = $this->elongation($planet, $yy, $mm, $dd, $hh, 0, 0);
408: if (($e0 >= 0.0) && ($e <= 0.0)) {
409: $cals[$yy][$mm][$dd + floor(($hh - 1) / 24)] = '内合';
410: $cnt++;
411: $e0 = $e;
412: break;
413: } else {
414: $e0 = $e;
415: }
416: }
417: } else if ($flag == 0) {
418: if ($e > $emax) {
419: $flag = +1;
420: } else {
421: $flag = -1;
422: }
423: // 東方最大離角
424: } else if ($flag > 0) {
425: if ($e > $emax) {
426: $emax = $e;
427: } else {
428: $emax = $this->elongation($planet, $yy, $mm, $dd, -48, 0, 0);
429: for ($hh = -47; $hh < 0; $hh++) {
430: $e = $this->elongation($planet, $yy, $mm, $dd, $hh, 0, 0);
431: if ($e > $emax) {
432: $emax = $e;
433: } else {
434: $cals[$yy][$mm][$dd + floor($hh / 24)] = '東方最大離角';
435: $cnt++;
436: $flag = -1;
437: $emin = $emax;
438: break;
439: }
440: }
441: }
442: // 西方最大離角
443: } else if ($flag < 0) {
444: if ($e < $emin) {
445: $emin = $e;
446: } else {
447: $emin = $this->elongation($planet, $yy, $mm, $dd, -48, 0, 0);
448: for ($hh = -47; $hh < 0; $hh++) {
449: $e = $this->elongation($planet, $yy, $mm, $dd, $hh, 0, 0);
450: if ($e < $emin) {
451: $emin = $e;
452: } else {
453: $cals[$yy][$mm][$dd + floor($hh / 24)] = '西方最大離角';
454: $cnt++;
455: $flag = +1;
456: $emax = $emin;
457: break;
458: }
459: }
460: }
461: }
462: $e0 = $e;
463: }
464: $mm++;
465: } while ($mm <= 12);
466:
467: return $cnt;
468: }

前述のメソッド elongation を利用し、毎日の離角を計算する。
すべての惑星は反時計回りに公転しているので、0をまたいで離角の符合が負から正へ変わるタイミングが外合である。ポイントが見つかったら、2日(48時間)前から1時間毎にステップ幅を細かくして、その日時を求める。このようにポイントが見つかったらステップ幅を細かくする処理は、他の天象の時にも行っている。
逆に、0をまたいで離角の符合が正から負へ変わるタイミングが内合である。
また、毎日の離角の最大値を変数 $emax に代入しておき、その $emax の値を下回るポイントが東方最大離角である。
逆に、毎日の離角の最小値を変数 $emin に代入しておき、その $emin の値を上回るポイントが西方最大離角である。

天象が起きる時刻を表示しようと考えたが、惑星の軌道要素は近似式であるため、実際の天象と数時間~数日の誤差があり、一覧に表示することは断念した。同様の理由も、東方最大離角・西方最大離角の時の離角も誤差が大きいため、一覧には表示しない。
解説:外惑星の天象を求める
pahooAstronomy.php
470: /**
471: * 指定した年の外惑星の天象を求める.
472: * 内惑星:衝, 合, 東矩, 西矩
473: * @param string $planet 惑星名(Mercury, Venus, ... Pluto)
474: * @param int $year 求めたい西暦年
475: * @param array $cals 暦を格納する配列
476: * [年][月][日] = 天象
477: * @return int 格納した天象の数
478: */
479: function planetPhenomenaOuter($planet, $year, &$cals) {
480: $cnt = 0; // 格納した天象の数
481:
482: // 指定年の前日(大晦日)から計算開始する.
483: $yy = $year - 1;
484: $mm = 12;
485: $dd = 31;
486: $e0 = $emin = $emax = $this->elongation($planet, $yy, $mm, $dd, 0, 0, 0);
487: $yy++;
488: $mm = 1;
489: do {
490: // 1ヶ月分のループ
491: $dayOfMonth = $this->getDaysInMonth($yy, $mm);
492: for ($dd = 1; $dd <= $dayOfMonth; $dd++) {
493: $e = $this->elongation($planet, $yy, $mm, $dd, 0, 0, 0);
494: // 衝
495: if (($e0 <= 0.0) && ($e >= 0.0)) {
496: for ($hh = -47; $hh <= 0; $hh++) {
497: $e = $this->elongation($planet, $yy, $mm, $dd, $hh, 0, 0);
498: if (($e0 <= 0.0) && ($e > 0.0)) {
499: $cals[$yy][$mm][$dd + floor(($hh - 1) / 24)] = '衝';
500: $cnt++;
501: $e0 = $e;
502: break;
503: } else {
504: $e0 = $e;
505: }
506: }
507: // 合
508: } else if (($e0 >= 0.0) && ($e <= 0.0)) {
509: for ($hh = -47; $hh < 0; $hh++) {
510: $e = $this->elongation($planet, $yy, $mm, $dd, $hh, 0, 0);
511: if (($e0 >= 0.0) && ($e <= 0.0)) {
512: $cals[$yy][$mm][$dd + floor(($hh - 1) / 24)] = '合';
513: $cnt++;
514: $e0 = $e;
515: break;
516: } else {
517: $e0 = $e;
518: }
519: }
520: // 東矩
521: } else if (($e0 >= +90.0) && ($e <= +90.0)) {
522: for ($hh = -47; $hh < 0; $hh++) {
523: $e = $this->elongation($planet, $yy, $mm, $dd, $hh, 0, 0);
524: if (($e0 >= +90.0) && ($e <= +90.0)) {
525: $cals[$yy][$mm][$dd + floor($hh / 24)] = '東矩';
526: $cnt++;
527: break;
528: } else {
529: $e0 = $e;
530: }
531: }
532: // 西矩
533: } else if (($e0 >= -90.0) && ($e < -90.0)) {
534: for ($hh = -47; $hh < 0; $hh++) {
535: $e = $this->elongation($planet, $yy, $mm, $dd, $hh, 0, 0);
536: if (($e0 >= -90.0) && ($e <= -90.0)) {
537: $cals[$yy][$mm][$dd + floor($hh / 24)] = '西矩';
538: $cnt++;
539: break;
540: } else {
541: $e0 = $e;
542: }
543: }
544: }
545: $e0 = $e;
546: }
547: $mm++;
548: } while ($mm <= 12);
549:
550: return $cnt;
551: }

内惑星と同様、0をまたいで離角の符合が負から正へ変わるタイミングが衝である。
逆に、0をまたいで離角の符合が正から負へ変わるタイミングが合である。
また、離角が90度になるタイミングが東矩、-90度になるタイミングが西矩である。
準備:惑星の天象を求める
pahooAstronomy.php
553: /**
554: * 指定した年の惑星の天象を求める.
555: * 惑星の天象とは‥‥
556: * 内惑星:外合, 内合, 東方最大離角, 西方最大離角, 留
557: * 外惑星:衝, 東矩, 西矩, 合
558: * @param string $planet 惑星名(Mercury, Venus, ... Pluto)
559: * @param int $year 求めたい西暦年
560: * @param array $cals 暦を格納する配列
561: * [年][月][日] = 天象
562: * @return int 格納した天象の数
563: */
564: function planetPhenomena($planet, $year, &$cals) {
565: // 内惑星の天象を求める.
566: if ($this->PlanetOrbitalElements[$planet][18] == '内惑星') {
567: $cnt = $this->planetPhenomenaInner($planet, $year, $cals);
568: // 外惑星の天象を求める.
569: } else {
570: $cnt = $this->planetPhenomenaOuter($planet, $year, $cals);
571: }
572: return $cnt;
573: }
準備:天象を一覧表示する
planetPhenomena.php
276: // 天象一覧を計算する.
277: if ($errmsg == '') {
278: $items = array(); // 全惑星の天象を格納する配列
279: $planetsEN = array();
280: $planetsJP = array();
281: $pa->getPlanetsEN($planetsEN);
282: $pa->getPlanetsJP($planetsJP);
283:
284: // 全惑星の天象を配列 $items に代入する
285: foreach ($planetsEN as $key=>$planet) {
286: $cals = array();
287: $pa->planetPhenomena($planet, $year, $cals);
288: for ($mm = 1; $mm <= 12; $mm++) {
289: $dayOfMonth = $pa->getDaysInMonth($year, $mm);
290: for ($dd = 1; $dd < $dayOfMonth; $dd++) {
291: if (isset($cals[$year][$mm][$dd])) {
292: $yyyymmdd = sprintf('%04d-%02d-%02d', $year, $mm, $dd);
293: $items[$yyyymmdd][$planetsJP[$key]] = $cals[$year][$mm][$dd];
294: }
295: }
296: }
297: }
298: // 配列を日付順にソートする.
299: ksort($items);
300:
301: // 一覧表(HTML)を作成する.
302: $table =<<< EOT
303: <table>
304: <tr><th>年月日</th><th>惑星</th><th>天象</th></tr>
305:
306: EOT;
307: foreach ($items as $yyyymmdd=>$item2) {
308: foreach ($item2 as $planet=>$phenomena) {
309: preg_match('/(\d{4})\-(\d{2})\-(\d{2})/', $yyyymmdd, $arr);
310: $ymd = sprintf('%04d年%02d月%02d日(%s)', $arr[1], $arr[2], $arr[3], $pa->getWeekString($arr[1], $arr[2], $arr[3]));
311: $table .= "<tr><td>{$ymd}</td><td>{$planet}</td><td>{$phenomena}</td></tr>\n";
312: }
313: }
314: }
315: $table .= "</table>\n";
316:
317: // 表示用HTMLを生成する.
318: $HtmlBody = makeCommonBody($year, $table, $errmsg);
多次元配列 $items を年月日(1次元目)でソートしたら、table タグを使った一覧表を作成する。
参考サイト
- PHPでホロスコープを描く:ぱふぅ家のホームページ
- 『かくして冥王星は降格された』(ニール・ド・グラス・タイソン/吉田三知世,2009年08月)
- 天象:国立天文台
今回は、「PHPでホロスコープを描く」で、地球を基点にする惑星の位置(地心黄道座標)を計算するプログラムを利用し、ある年の惑星の天象を一覧表示するPHPプログラムを作ることにする。
2006年(平成18年)、冥王星は矮惑星に降格になったが、ここでは冥王星の天象も一覧に含める。