サンプル・プログラムの実行例
目次
サンプル・プログラムのダウンロード
gengo2gregorian.php | サンプル・プログラム本体。 |
解説:元号の開始と終了
37: //元号=西暦一覧
38: $eraTable = array(
39: '明治' => array('from'=>'18680125', 'to'=>'19120729'),
40: '大正' => array('from'=>'19120730', 'to'=>'19261224'),
41: '昭和' => array('from'=>'19261225', 'to'=>'19890107'),
42: '平成' => array('from'=>'19890108', 'to'=>'20190430'),
43: '令和' => array('from'=>'20190501', 'to'=>'29991231')
44: );
あらたに作るのは、元号の切り替わり(例:昭和64年1月7日の翌日は平成元年1月8日)に注意して年月日のプルダウンを制御する部分である。そのために、あらかじめ西暦と元号の関係表をグローバル変数 $eraTable に用意しておく。
解説:西暦年月日を元号に変換
180: /**
181: * 西暦年月日を元号に変換
182: * @param int $year 西暦年
183: * @param int $month 月
184: * @param int $day 日
185: * @return array era=元号, year=元号年, month=月, day=日
186: */
187: function ad2era($year, $month, $day) {
188: global $eraTable;
189:
190: $res = array('era'=>'', 'year'=>$year, 'month'=>$month, 'day'=>$day);
191: $yyyymmdd = sprintf('%04d%02d%02d', $year, $month, $day);
192:
193: foreach ($eraTable as $era=>$val) {
194: if ($yyyymmdd <= $val['to']) {
195: $res['era'] = $era;
196: $y = (int)substr($eraTable[$eraset['era']]['from'], 0, 4);
197: $res['year'] = $year - $y + 1;
198: break;
199: }
200: }
201:
202: return $res;
203: }
解説:元号を西暦年月日に変換
205: /**
206: * 元号を西暦年月日に変換
207: * @param array eraset 元号年月日 era=元号, year=元号年, month=月, day=日
208: * @return array year=西暦年, month=月, day=日
209: */
210: function era2ad($eraset) {
211: global $eraTable;
212:
213: $res = array('year'=>$eraset['year'], 'month'=>$eraset['month'], 'day'=>$eraset['day']);
214: $yyyymmdd = $eraTable[$eraset['era']]['from'];
215: $year = (int)substr($yyyymmdd, 0, 4);
216: $res['year'] = $eraset['year'] + $year - 1;
217:
218: return $res;
219: }
解説:指定した元号の年数・月数・日数
221: /**
222: * 指定した元号の年数・月数・日数を返す
223: * @param array $eraset 元号年月日 era=元号, year=元号年, month=月, day=日
224: * @return array yy=年数, mm=月数, dd=日数
225: */
226: function getYymmddInEra($eraset) {
227: global $eraTable;
228:
229:
230: $res = era2ad($eraset); //元号を西暦年月日に変換
231: $year = $res['year'];
232:
233: //年数
234: $y0 = (int)substr($eraTable[$eraset['era']]['from'], 0, 4);
235: $y1 = (int)substr($eraTable[$eraset['era']]['to'], 0, 4);
236: $yy = $y1 - $y0 + 1;
237: if ($eraset['year'] > $yy) {
238: $eraset['year'] = 1;
239: $res = era2ad($eraset); //元号を西暦年月日に変換
240: $year = $res['year'];
241: }
242:
243: //月数
244: if ($year == $y0) {
245: $m0 = (int)substr($eraTable[$eraset['era']]['from'], 4, 2);
246: $m1 = 12;
247: if ($eraset['month'] < $m0) $eraset['month'] = $m0;
248: } else if ($year == $y1) {
249: $m0 = 1;
250: $m1 = (int)substr($eraTable[$eraset['era']]['to'], 4, 2);
251: if ($eraset['month'] > $m1) $eraset['month'] = $m1;
252: } else {
253: $m0 = 1;
254: $m1 = 12;
255: }
256:
257: //日数
258: $ym0 = substr($eraTable[$eraset['era']]['from'], 0, 6);
259: $ym1 = substr($eraTable[$eraset['era']]['to'], 0, 6);
260: $yymm = sprintf('%04d%02d', $year, $eraset['month']);
261:
262: static $days = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
263: $days[2] = isLeapYear($year) ? 29 : 28; //閏年の判定
264: if ($yymm == $ym0) {
265: $d0 = (int)substr($eraTable[$eraset['era']]['from'], 6, 2);
266: $d1 = $days[$eraset['month']];
267: if ($eraset['day'] < $d0) $eraset['day'] = $d0;
268: } else if ($yymm == $ym1) {
269: $d0 = 1;
270: $d1 = (int)substr($eraTable[$eraset['era']]['to'], 6, 2);
271: if ($eraset['day'] > $d1) $eraset['day'] = $d1;
272: } else {
273: $d0 = 1;
274: $d1 = $days[$eraset['month']];
275: }
276:
277: return array('yy'=>array('from'=>1, 'to'=>$yy), 'mm'=>array('from'=>$m0, 'to'=>$m1), 'dd'=>array('from'=>$d0, 'to'=>$d1));
278: }
そこで、引数として元号年月日を渡すと、年・月・日の範囲を配列で返すユーザー関数が getYymmddInEra である。
同時に、閏年のときは2月29日になるようにする。
解説:元号年月日をプルダウンメニューにする
360: //プルダウンメニュー
361: $outstr = '';
362: $name = 'exec';
363: //元号セレクタ
364: $outstr .=<<< EOT
365: <select name="era" id="era" onChange="submit();">
366:
367: EOT;
368: $eraset2['era'] = '';
369: foreach ($eraTable as $era=>$val) {
370: if ($era == $eraset['era']) {
371: $selected = 'selected';
372: $eraset2['era'] = $era;
373: } else {
374: $selected = '';
375: }
376: $outstr .=<<< EOT
377: <option value="{$era}" {$selected}>{$era}</option>
378:
379: EOT;
380: }
381: $outstr .=<<< EOT
382: </select>
383:
384: EOT;
385:
386: //年号セレクタ
387: $outstr .=<<< EOT
388: <select name="year" id="year" onChange="submit();">
389:
390: EOT;
391: $eraset2['year'] = 0;
392: for ($yy = $res['yy']['from']; $yy <= $res['yy']['to']; $yy++) {
393: if ($yy == $eraset['year']) {
394: $selected = 'selected';
395: $eraset2['year'] = $yy;
396: } else {
397: $selected = '';
398: }
399: $yn = ($yy == 1) ? '元' : $yy;
400: $outstr .=<<< EOT
401: <option value="{$yy}" {$selected}>{$yn}</option>
402:
403: EOT;
404: }
405: $outstr .=<<< EOT
406: </select>年
407:
408: EOT;
409:
410: //月セレクタ
411: $outstr .=<<< EOT
412: <select name="month" id="month" onChange="submit();">
413:
414: EOT;
415: $eraset2['month'] = 1;
416: for ($mm = $res['mm']['from']; $mm <= $res['mm']['to']; $mm++) {
417: if ($mm == $eraset['month']) {
418: $selected = 'selected';
419: $eraset2['month'] = $mm;
420: } else {
421: $selected = '';
422: }
423: $outstr .=<<< EOT
424: <option value="{$mm}" {$selected}>{$mm}</option>
425:
426: EOT;
427: }
428: $outstr .=<<< EOT
429: </select>月
430:
431: EOT;
432:
433: //日セレクタ
434: $outstr .=<<< EOT
435: <select name="day" id="day" onChange="submit();">
436:
437: EOT;
438: $eraset2['day'] = 1;
439: for ($dd = $res['dd']['from']; $dd <= $res['dd']['to']; $dd++) {
440: if ($dd == $eraset['day']) {
441: $selected = 'selected';
442: $eraset2['day'] = $dd;
443: } else {
444: $selected = '';
445: }
446: $outstr .=<<< EOT
447: <option value="{$dd}" {$selected}>{$dd}</option>
448:
449: EOT;
450: }
451:
452: $ad = era2ad($eraset2); //元号を西暦年月日に変換
453: $outstr .=<<< EOT
454: </select>日
455:
456: <p>西暦 {$ad['year']} 年 {$ad['month']} 月 {$ad['day']} 日</p>
457:
458: EOT;
459:
460: $body =<<< EOT
このプルダウンメニューが変化したら、JavaScript の onChange イベントで submit 駆動し、form 内容を送信するようにしている。これは元号(era)、年(year)、月(month)の場合も同様で、これを行うことで、元号・年・月・日を変更した際に再計算を行う。
ただし、いちいちサーバサイドで計算させることはサーバに負荷がかかるので、この処理は、本来はクライアントサイドでJavaScriptで行わせるのが良いだろう。JavaScriptによる処理については、「元号による年月日セレクタ」で紹介している。
参考サイト
- PHPで年月日を入力:ぱふぅ家のホームページ
- PHPで日本語対応dateを作る:ぱふぅ家のホームページ
- PHPで祝日を求める:ぱふぅ家のホームページ
- PHPで閏年かどうか判定する:ぱふぅ家のホームページ
- PHPでテキスト中の和暦・西暦年号を統一する*
- jQueryで元号年月日セレクタを用意する:ぱふぅ家のホームページ
- C++ でテキスト中の和暦・西暦年号を統一する:ぱふぅ家のホームページ
参考書籍
元号って何だ? | |||
著者 | 藤井 青銅 | ||
出版社 | 小学館 | ||
サイズ | 新書 | ||
発売日 | 2019年02月01日頃 | ||
価格 | 880円(税込) | ||
ISBN | 9784098253395 | ||
元号に関する素朴な疑問に答える入門書。そしていまいちばん楽しめる元号本。多くの日本人は平成⇒昭和⇒大正⇒明治まで遡ることができても明治の一つ前の元号を言うことができない。だから元号というと難しく感じる人もいるが、じつはとても人間くさくて面白いものなのだ。本書では全部で247ある元号をいろいろなランキングを使って解説。またさまざまな元号由来のネーミングや全国の改元ゆかりの地などを紹介する。まったく新しい元号読み物! | |||
(2021年5月10日)元号変更年における月・日の選択動作改善
(2021年4月24日)PHP8対応,リファラ・チェック改良