目次
サンプル・プログラムの実行例
サンプル・プログラム
| cosmicCalendar.php | サンプル・プログラム本体。 |
| cosmicCalendar.xml | イベント・ファイル。 |
| pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
| pahooCalendar.php | 暦計算クラス pahooCalendar。 暦計算クラスの使い方は「PHPで日出没・月出没・月齢・潮を計算」を参照。include_path が通ったディレクトリに配置すること。 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 1.7.0 | 2025/12/06 | jQueryを使わない.PHP8.5対応:double→float |
| 1.6.0 | 2023/10/15 | sigcalendar()のbug-fix, pahooInputData導入 |
| 1.5.0 | 2022/12/30 | 1月は時分まで表示するようにした |
| 1.42 | 2022/07/21 | bug-fix,イベント・ファイル更新 |
| 1.41 | 2021/05/12 | bug-fix |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 2.0.1 | 2025/08/11 | getParam() bug-fix |
| 2.0.0 | 2025/08/11 | pahooLoadEnv() 追加 |
| 1.9.0 | 2025/07/26 | getParam() 引数に$trim追加 |
| 1.8.1 | 2025/03/15 | validRegexPattern() debug |
| 1.8.0 | 2024/11/12 | validRegexPattern() 追加 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 4.6.1 | 2025/11/23 | next_fullmoon: bug-fix |
| 4.6.0 | 2025/10/08 | getMidAutumnMoon() 追加 |
| 4.5.1 | 2025/05/31 | deg2ddmm(), deg2hhmm() 不具合修正 |
| 4.5.0 | 2024/03/17 | ヒジュラ暦メソッドを追加 |
| 4.4.1 | 2024/03/17 | getCabinetOfficeHolidayTable() -- bug-fix |
イベント・ファイル
同梱したファイルには、宇宙の誕生から現在までの主要イベントを記入済みである。
このイベント・ファイルを編集すれば、日本史や家族史を使った宇宙カレンダー(365日カレンダーと呼んだ方がいいかもしれない)を表示することができる。
cosmicCalendar.xml
1: <?xml version="1.0" encoding="utf-8" ?>
2: <!-- 年代記 -->
3: <cosmicCalendar>
4: <!-- キャプション -->
5: <caption>
6: <label>宇宙カレンダー</label>
7: <description>宇宙誕生から現在までを1年に圧縮</description>
8: </caption>
9: <!-- 開始 -->
10: <start>
11: <label>宇宙誕生</label>
12: <before unit="year">138E+8</before>
13: <description></description>
14: </start>
15: <finish>
16: <label>現在</label>
17: <before unit="year">0</before>
18: <description></description>
19: </finish>
20:
21: <!-- 以下、イベント・データベース -->
22: <event>
23: <label>宇宙の晴れ上がり</label>
24: <!-- 開始イベントからの年数を記載するときは after -->
25: <after unit="year">30E+4</after>
26: <description></description>
27: </event>
28: <event>
29: <label>天の川銀河の誕生</label>
30: <!-- 現在から××年前を記載するときは before -->
31: <before unit="year">110E+8</before>
32: <description></description>
33: </event>
34: <event>
35: <label>太平洋戦争終結</label>
36: <!-- 西暦記載するときは dt で yyyy/mm/dd hh:mm:ss形式 -->
37: <dt>1945/8/15 00:00:00</dt>
38: <description></description>
39: </event>
40: <event>
41: <label>ハンムラビ王の即位</label>
42: <!-- 紀元前はマイナス表記 -->
43: <dt>-1792/1/1 00:00:00</dt>
44: <description></description>
45: </event>
46: <event>
47: <label>最古のガンマ線バースト</label>
48: <after unit="year">7.3E+8</after>
49: <description>GRB 250314A -- 2025年3月14日に、フランスと中国の天文衛星「SVOM」がとらえた。</description>
50: </event>
準備:外部クラスなど
そこで、クラスファイル "pahooCalendar.php" を require_once し、オブジェクトを生成する。
解説:イベント・ファイルを読み込み、ソートする
cosmicCalendar.php
281: /**
282: * イベント・ファイルを読み込み、ソートする
283: * @param string $fname イベント・ファイル名
284: * @param array $caldb イベントを格納する配列
285: * @param array $caption キャプションを格納する配列
286: * @return bool TRUE/FALSE
287: */
288: function readDB($fname, &$caldb, &$caption) {
289: $pcl = new pahooCalendar(); // pahooCalendarクラス
290: $pcl->setLanguage('jp');
291:
292: $jd_end = $pcl->Gregorian2JD(date('Y') + 1, 1, 1, 0, 0, 0); // 今年の最後
293: $dd = 365 + date('L'); // 1年の日数
294: $res = FALSE;
295:
296: // イベント・ファイル読み込み
297: if (file_exists($fname)) {
298: $xml = simplexml_load_file($fname);
299: // キャプション
300: if (isset($xml->caption->label)) {
301: $caption['label'] = isset($xml->caption->label) ? (string)$xml->caption->label : '宇宙カレンダー';
302: $caption['description'] = isset($xml->caption->description) ? (string)$xml->caption->description : '宇宙誕生から現在までを1年に圧縮';
303: }
304: // 開始
305: if (isset($xml->start->before)) {
306: $start = (float)$xml->start->before;
307: $unit = ($dd * 24 * 60 * 60) / $start; // 1秒当たり年数
308: $cnt = 0;
309: $caldb[$cnt]['label'] = (string)$xml->start->label;
310: $ss = $start * $unit;
311: list($caldb[$cnt]['dt'], $caldb[$cnt]['fmt']) = sigcalendar($ss);
312: $cnt++;
313: }
314: // イベント読み込み
315: foreach ($xml->event as $event) {
316: $caldb[$cnt]['label'] = (string)$event->label;
317: if (isset($event->before)) {
318: $ss = ($start - (float)$event->before) * $unit;
319: } else if (isset($event->after)) {
320: $ss = (float)$event->after * $unit;
321: } else if (isset($event->dt)) {
322: sscanf((string)$event->dt, '%d/%d/%d %d:%d:%f', $year, $month, $day, $hour, $min, $sec);
323: $jd = $pcl->Gregorian2JD($year, $month, $day, $hour, $min, $sec);
324: $ss = ($start - ($jd_end - $jd) / $dd) * $unit;
325: } else {
326: $ss = 0;
327: }
328: // カレンダー計算
329: list($caldb[$cnt]['dt'], $caldb[$cnt]['fmt']) = sigcalendar($ss);
330: $cnt++;
331: }
332: $res = TRUE;
333: }
334: $pcl = NULL;
335:
336: // ソート
337: usort($caldb, function ($a, $b) {
338: if (! isset($a['dt'])) return NULL;
339: if (! isset($b['dt'])) return NULL;
340: return $a['dt'] > $b['dt'] ? (+1) : (-1);
341: });
342:
343: return $res;
344: }
個々のイベント要素を読み込む際は、年数の表記が before, after, dt によって場合分けを行い、宇宙誕生(startに記述)を基準点として、そこから何秒の距離にあるかを変数 $ss に代入する。
イベントを、基準点と、その距離に置換することで、宇宙史だけでなく、日本史や家族史のような、スケールの異なるカレンダーも作ることができる。
解説:カレンダー計算
cosmicCalendar.php
228: /**
229: * カレンダー計算
230: * @param float $ss 秒数
231: * @return array(カレンダー,フォーマット)
232: */
233: function sigcalendar($ss) {
234: $yyyy = date('Y'); // 今年の西暦年
235: $tt = (int)strtotime($yyyy .'/1/1 0:0:0') + (int)$ss;
236: $dt = date('m/d H:i:s', $tt);
237:
238: // 01/01 00:00:01以前→ミリ秒まで
239: if (preg_match('/^01\/01 01:01:01/', $dt) > 0) {
240: $fmt = 'm/d H:i:s';
241: $dt = date($fmt, $tt);
242: $dt .= sprintf('.%03d', (($ss - floor($ss)) * 1000));
243: // 01/01 4時以前→秒まで
244: } else if (preg_match('/^12\/31 0[0-4]./', $dt) > 0) {
245: $fmt = 'm/d H:i:s';
246: $dt = date($fmt, $tt);
247: // 01/01→分まで
248: } else if (preg_match('/^01\/01/', $dt) > 0) {
249: $fmt = 'm/d H:i';
250: $dt = date($fmt, $tt);
251: // 1月→時まで
252: } else if (preg_match('/^01/', $dt) > 0) {
253: $fmt = 'm/d H:00';
254: $dt = date($fmt, $tt);
255: // 12/31 23:59:59以降→ミリ秒まで
256: } else if (preg_match('/^12\/31 23:59:59/', $dt) > 0) {
257: $fmt = 'm/d H:i:s';
258: $dt = date($fmt, $tt);
259: $dt .= sprintf('.%03d', (($ss - floor($ss)) * 1000));
260: // 12/31 20時以降→秒まで
261: } else if (preg_match('/^12\/31 2/', $dt) > 0) {
262: $fmt = 'm/d H:i:s';
263: $dt = date($fmt, $tt);
264: // 12/31→分まで
265: } else if (preg_match('/^12\/31/', $dt) > 0) {
266: $fmt = 'm/d H:i';
267: $dt = date($fmt, $tt);
268: // 12月→時まで
269: } else if (preg_match('/^12/', $dt) > 0) {
270: $fmt = 'm/d H:00';
271: $dt = date($fmt, $tt);
272: // それ以前→日まで
273: } else {
274: $fmt = 'm/d';
275: $dt = date($fmt, $tt);
276: }
277:
278: return array($dt, $fmt);
279: }
そこで、一定の境界条件を設け、カレンダーの時分秒を表示しなかったり、逆にミリ秒まで表示するようにした。
これを行うのがユーザー関数 sigcalendar である。
解説:データベースに表示用フラグを立てる
cosmicCalendar.php
346: /**
347: * データベースに表示用フラグを立てる:全部
348: * @param array $caldb データベース
349: * @param int $ti マークしたい時刻(省略時は現在時刻)
350: * @return なし
351: */
352: function checkDB_all(&$caldb, $ti=0) {
353: if ($ti == 0) $ti = time(); // 省略時
354:
355: $key = 0;
356: $flag = (-1);
357: foreach ($caldb as $rec) {
358: if (isset($rec['dt'])) {
359: $t0 = date($rec['fmt'], $ti);
360: if ($rec['dt'] < $t0) {
361: $caldb[$key]['flag'] = $flag;
362: } else if ($flag == (-1)) {
363: $flag++;
364: $caldb[$key]['flag'] = $flag;
365: $flag++;
366: } else {
367: $caldb[$key]['flag'] = $flag;;
368: }
369: $key++;
370: }
371: }
372: }
cosmicCalendar.php
374: /**
375: * データベースに表示用フラグを立てる:同じ月
376: * @param array $caldb データベース
377: * @param int $ti マークしたい時刻(省略時は現在時刻)
378: * @return なし
379: */
380: function checkDB_month(&$caldb, $ti=0) {
381: if ($ti == 0) $ti = time(); // 省略時
382: $t1 = date('m', $ti);
383:
384: $flag = (-2);
385: $key = 0;
386: foreach ($caldb as $rec) {
387: if (isset($rec['dt'])) {
388: $t0 = date($rec['fmt'], $ti);
389: if ($rec['dt'] < $t0) {
390: $caldb[$key]['flag'] = $flag;
391: } else if ($flag == (-2)) {
392: $caldb[$key]['flag'] = 0;
393: $flag = (+2);
394: } else {
395: $caldb[$key]['flag'] = $flag;
396: }
397: if (preg_match('/(^\d{2})/iu', $rec['dt'], $arr) > 0) {
398: if (($arr[1] == $t1) && ($caldb[$key]['flag']) != 0) {
399: $caldb[$key]['flag'] = (-1);
400: }
401: }
402: $key++;
403: }
404: }
405: }
cosmicCalendar.php
407: /**
408: * データベースに表示用フラグを立てる:「今ここ」と前後2件ずつ
409: * @param array $caldb データベース
410: * @param int $ti マークしたい時刻(省略時は現在時刻)
411: * @return なし
412: */
413: function checkDB_now(&$caldb, $ti=0) {
414: if ($ti == 0) $ti = time(); // 省略時
415:
416: $flag = (-2);
417: $key = 0;
418: foreach ($caldb as $rec) {
419: if (isset($rec['dt'])) {
420: $t0 = date($rec['fmt'], $ti);
421: if ($rec['dt'] < $t0) {
422: $caldb[$key]['flag'] = $flag;
423: $key++;
424: } else if ($flag == (-2)) {
425: $flag++;
426: for ($i = $key - 2; $i < $key; $i++) {
427: if (isset($caldb[$i]['label'])) $caldb[$i]['flag'] = $flag;
428: }
429: $flag++;
430: $i = $key;
431: if (isset($caldb[$i]['label'])) $caldb[$i]['flag'] = $flag;
432: $flag++;
433: $key++;
434: $caldb[$key]['flag'] = $flag;
435: $key++;
436: if (isset($caldb[$key]['label'])) $caldb[$key]['flag'] = $flag;
437: $key++;
438: $flag++;
439: } else {
440: $caldb[$key]['flag'] = $flag;
441: $key++;
442: }
443: }
444: }
445: }
こららを処理するのが、ユーザー関数 checkDB_all, checkDB_month, checkDB_now である。
解説:宇宙カレンダーを作成
cosmicCalendar.php
465: /**
466: * 宇宙カレンダーを作成:テーブル形式
467: * @param array $caldb データベース
468: * @param array $caption キャプション
469: * @return string 表示用コンテンツ
470: */
471: function makeCosmicCalendar_table($caldb, $caption) {
472: $outstr =<<< EOT
473: <table class="stripe">
474: <caption>{$caption['label']}</caption>
475: <tr><th>日時</th><th>イベント</th></tr>
476:
477: EOT;
478:
479: foreach ($caldb as $rec) {
480: if ($rec['flag'] >= (-1) && $rec['flag'] <= (+1)) {
481: $mark = ($rec['flag'] == 0) ? ' ⏱' : '';
482: $outstr .=<<< EOT
483: <tr>
484: <td>{$rec['dt']}$mark</td>
485: <td>{$rec['label']}</td>
486: </tr>
487:
488: EOT;
489: }
490: }
491: $outstr .=<<< EOT
492: </table>
493:
494: EOT;
495: return $outstr;
496: }
cosmicCalendar.php
447: /**
448: * 宇宙カレンダーを作成:テキスト形式
449: * @param array $caldb データベース
450: * @param array $caption キャプション
451: * @return string 表示用コンテンツ
452: */
453: function makeCosmicCalendar_text($caldb, $caption) {
454: $outstr = "<hr>■{$caption['label']}({$caption['description']})<br>\n";
455: foreach ($caldb as $rec) {
456: if ($rec['flag'] >= (-1) && $rec['flag'] <= (+1)) {
457: $outstr .= $rec['dt'] . ' - ' . $rec['label'];
458: if ($rec['flag'] == 0) $outstr .= '←いまココ';
459: $outstr .= "<br>\n";
460: }
461: }
462: return $outstr;
463: }
参考サイト
- コズミックカレンダー:高校生のためのおもしろ歴史教室
- 地球人類学:文化人類学解放講座(2016年度ブログ版)

アメリカの天文学者で作家の故カール・セーガン氏が考案したとされ、パパぱふぅは学生時代、セーガン氏が進行担当したテレビ番組「コスモス」や、来日した際の講演などを聞き、当時は電卓で計算し、ノートに記入したものだ。
今回は、PHPを使い、あらかじめ用意した年表データを宇宙カレンダーに変換し、表示するプログラムを作る。なお、年表データを、たとえば日本史や家族史に置き換えれば、オリジナルの宇宙カレンダーを作ることができる。
(2026年1月3日)jQueryを使わない.PHP8.5対応:double→float