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

目次
サンプル・プログラムのダウンロード
gengo2gregorian.php | サンプル・プログラム本体。 |
解説:元号の開始と終了
0037: //元号=西暦一覧
0038: $eraTable = array(
0039: '明治' => array('from'=>'18680125', 'to'=>'19120729'),
0040: '大正' => array('from'=>'19120730', 'to'=>'19261224'),
0041: '昭和' => array('from'=>'19261225', 'to'=>'19890107'),
0042: '平成' => array('from'=>'19890108', 'to'=>'20190430'),
0043: '令和' => array('from'=>'20190501', 'to'=>'29991231')
0044: );

あらたに作るのは、元号の切り替わり(例:昭和64年1月7日の翌日は平成元年1月8日)に注意して年月日のプルダウンを制御する部分である。そのために、あらかじめ西暦と元号の関係表をグローバル変数 $eraTable に用意しておく。
解説:西暦年月日を元号に変換
0180: /**
0181: * 西暦年月日を元号に変換
0182: * @param int $year 西暦年
0183: * @param int $month月
0184: * @param int $day 日
0185: * @return array era=元号, year=元号年, month=月, day=日
0186: */
0187: function ad2era($year, $month, $day) {
0188: global $eraTable;
0189:
0190: $res = array('era'=>'', 'year'=>$year, 'month'=>$month, 'day'=>$day);
0191: $yyyymmdd = sprintf('%04d%02d%02d', $year, $month, $day);
0192:
0193: foreach ($eraTable as $era=>$val) {
0194: if ($yyyymmdd <= $val['to']) {
0195: $res['era'] = $era;
0196: $y = (int)substr($eraTable[$eraset['era']]['from'], 0, 4);
0197: $res['year'] = $year - $y + 1;
0198: break;
0199: }
0200: }
0201:
0202: return $res;
0203: }
解説:元号を西暦年月日に変換
0205: /**
0206: * 元号を西暦年月日に変換
0207: * @param array eraset 元号年月日era=元号, year=元号年, month=月, day=日
0208: * @return array year=西暦年, month=月, day=日
0209: */
0210: function era2ad($eraset) {
0211: global $eraTable;
0212:
0213: $res = array('year'=>$eraset['year'], 'month'=>$eraset['month'], 'day'=>$eraset['day']);
0214: $yyyymmdd = $eraTable[$eraset['era']]['from'];
0215: $year = (int)substr($yyyymmdd, 0, 4);
0216: $res['year'] = $eraset['year'] + $year - 1;
0217:
0218: return $res;
0219: }
解説:指定した元号の年数・月数・日数
0221: /**
0222: * 指定した元号の年数・月数・日数を返す
0223: * @param array $eraset元号年月日era=元号, year=元号年, month=月, day=日
0224: * @return array yy=年数, mm=月数, dd=日数
0225: */
0226: function getYymmddInEra($eraset) {
0227: global $eraTable;
0228:
0229:
0230: $res = era2ad($eraset); //元号を西暦年月日に変換
0231: $year = $res['year'];
0232:
0233: //年数
0234: $y0 = (int)substr($eraTable[$eraset['era']]['from'], 0, 4);
0235: $y1 = (int)substr($eraTable[$eraset['era']]['to'], 0, 4);
0236: $yy = $y1 - $y0 + 1;
0237: if ($eraset['year'] > $yy) {
0238: $eraset['year'] = 1;
0239: $res = era2ad($eraset); //元号を西暦年月日に変換
0240: $year = $res['year'];
0241: }
0242:
0243: //月数
0244: if ($year == $y0) {
0245: $m0 = (int)substr($eraTable[$eraset['era']]['from'], 4, 2);
0246: $m1 = 12;
0247: if ($eraset['month'] < $m0) $eraset['month'] = $m0;
0248: } else if ($year == $y1) {
0249: $m0 = 1;
0250: $m1 = (int)substr($eraTable[$eraset['era']]['to'], 4, 2);
0251: if ($eraset['month'] > $m1) $eraset['month'] = $m1;
0252: } else {
0253: $m0 = 1;
0254: $m1 = 12;
0255: }
0256:
0257: //日数
0258: $ym0 = substr($eraTable[$eraset['era']]['from'], 0, 6);
0259: $ym1 = substr($eraTable[$eraset['era']]['to'], 0, 6);
0260: $yymm = sprintf('%04d%02d', $year, $eraset['month']);
0261:
0262: static $days = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
0263: $days[2] = isleap($year) ? 29 : 28; //閏年の判定
0264: if ($yymm == $ym0) {
0265: $d0 = (int)substr($eraTable[$eraset['era']]['from'], 6, 2);
0266: $d1 = $days[$eraset['month']];
0267: if ($eraset['day'] < $d0) $eraset['day'] = $d0;
0268: } else if ($yymm == $ym1) {
0269: $d0 = 1;
0270: $d1 = (int)substr($eraTable[$eraset['era']]['to'], 6, 2);
0271: if ($eraset['day'] > $d1) $eraset['day'] = $d1;
0272: } else {
0273: $d0 = 1;
0274: $d1 = $days[$eraset['month']];
0275: }
0276:
0277: return array('yy'=>array('from'=>1, 'to'=>$yy), 'mm'=>array('from'=>$m0, 'to'=>$m1), 'dd'=>array('from'=>$d0, 'to'=>$d1));
0278: }
そこで、引数として元号年月日を渡すと、年・月・日の範囲を配列で返すユーザー関数が getYymmddInEra である。
同時に、閏年のときは2月29日になるようにする。
解説:元号年月日をプルダウンメニューにする
0360: //プルダウンメニュー
0361: $outstr = '';
0362: $name = 'exec';
0363: //元号セレクタ
0364: $outstr .=<<< EOT
0365: <select name="era" id="era" onChange="submit();">
0366:
0367: EOT;
0368: $eraset2['era'] = '';
0369: foreach ($eraTable as $era=>$val) {
0370: if ($era == $eraset['era']) {
0371: $selected = 'selected';
0372: $eraset2['era'] = $era;
0373: } else {
0374: $selected = '';
0375: }
0376: $outstr .=<<< EOT
0377: <option value="{$era}" {$selected}>{$era}</option>
0378:
0379: EOT;
0380: }
0381: $outstr .=<<< EOT
0382: </select>
0383:
0384: EOT;
0385:
0386: //年号セレクタ
0387: $outstr .=<<< EOT
0388: <select name="year" id="year" onChange="submit();">
0389:
0390: EOT;
0391: $eraset2['year'] = 0;
0392: for ($yy = $res['yy']['from']; $yy <= $res['yy']['to']; $yy++) {
0393: if ($yy == $eraset['year']) {
0394: $selected = 'selected';
0395: $eraset2['year'] = $yy;
0396: } else {
0397: $selected = '';
0398: }
0399: $yn = ($yy == 1) ? '元' : $yy;
0400: $outstr .=<<< EOT
0401: <option value="{$yy}" {$selected}>{$yn}</option>
0402:
0403: EOT;
0404: }
0405: $outstr .=<<< EOT
0406: </select>年
0407:
0408: EOT;
0409:
0410: //月セレクタ
0411: $outstr .=<<< EOT
0412: <select name="month" id="month" onChange="submit();">
0413:
0414: EOT;
0415: $eraset2['month'] = 1;
0416: for ($mm = $res['mm']['from']; $mm <= $res['mm']['to']; $mm++) {
0417: if ($mm == $eraset['month']) {
0418: $selected = 'selected';
0419: $eraset2['month'] = $mm;
0420: } else {
0421: $selected = '';
0422: }
0423: $outstr .=<<< EOT
0424: <option value="{$mm}" {$selected}>{$mm}</option>
0425:
0426: EOT;
0427: }
0428: $outstr .=<<< EOT
0429: </select>月
0430:
0431: EOT;
0432:
0433: //日セレクタ
0434: $outstr .=<<< EOT
0435: <select name="day" id="day" onChange="submit();">
0436:
0437: EOT;
0438: $eraset2['day'] = 1;
0439: for ($dd = $res['dd']['from']; $dd <= $res['dd']['to']; $dd++) {
0440: if ($dd == $eraset['day']) {
0441: $selected = 'selected';
0442: $eraset2['day'] = $dd;
0443: } else {
0444: $selected = '';
0445: }
0446: $outstr .=<<< EOT
0447: <option value="{$dd}" {$selected}>{$dd}</option>
0448:
0449: EOT;
0450: }
0451:
0452: $ad = era2ad($eraset2); //元号を西暦年月日に変換
0453: $outstr .=<<< EOT
0454: </select>日
0455:
0456: <p>西暦 {$ad['year']} 年 {$ad['month']} 月 {$ad['day']} 日</p>
0457:
0458: EOT;
0459:
0460: $body =<<< EOT

このプルダウンメニューが変化したら、JavaScript の onChange イベントで submit 駆動し、form 内容を送信するようにしている。これは元号(era)、年(year)、月(month)の場合も同様で、これを行うことで、元号・年・月・日を変更した際に再計算を行う。

ただし、いちいちサーバサイドで計算させることはサーバに負荷がかかるので、この処理は、本来はクライアントサイドでJavaScriptで行わせるのが良いだろう。JavaScriptによる処理については、「元号による年月日セレクタ」で紹介している。
参考サイト
- PHPで年月日を入力:ぱふぅ家のホームページ
- PHPで日本語対応dateを作る:ぱふぅ家のホームページ
- PHPで祝日を求める:ぱふぅ家のホームページ
- PHPで閏年かどうか判定する:ぱふぅ家のホームページ
- 元号による年月日セレクタ:ぱふぅ家のホームページ
(2021年5月10日)元号変更年における月・日の選択動作改善
(2021年4月24日)PHP8対応,リファラ・チェック改良