jQueryで元号年月日セレクタを用意する

(1/1)
jQueryで年月日セレクタを用意する」では、西暦年月日を入力するJavaScriptを紹介したが、今回は、西暦年の部分を元号で選択できるようにする。処理の流れは、「PHPで元号年月日入力(プルダウン方式)」を参考にしている。
元号の切り替わり(例:昭和64年1月7日の翌日は平成元年1月8日)に注意し、存在しない年月日は入力できないようにする。また、日数は大の月と小の月によって変わるようにし、とくに閏年の2月の入力に気をつける。

サンプル・プログラムのダウンロード

圧縮ファイルの内容
jsgengo.htmlサンプル・プログラム本体。

プログラムの目標

PHPで元号年月日入力

解説:元号の開始と終了

  25: //元号=西暦一覧
  26: var eraTable = {
  27:     '明治'  : {'from':'18680125', 'to':'19120729'},
  28:     '大正'  : {'from':'19120730', 'to':'19261224'},
  29:     '昭和'  : {'from':'19261225', 'to':'19890107'},
  30:     '平成'  : {'from':'19890108', 'to':'20190430'},
  31:     '令和'  : {'from':'20190501', 'to':'29991231'}
  32: };

元号の切り替わり(例:昭和64年1月7日の翌日は平成元年1月8日)に注意して年月日のプルダウンを制御するために、あらかじめ西暦と元号の関係表をグローバル変数 eraTable に用意しておく。
2019年(令和元年)5月1日の新元号が決まったら、文字列 '新元号' を変更すればいい。新元号の終了日は未定なので、とりあえず2999年(令和981年)12月31日としている。

解説:西暦年月日を元号に変換

 153: /**
 154:  * 西暦年月日を元号に変換
 155:  * @param   int year  西暦年
 156:  * @param   int month 月
 157:  * @param   int date  日
 158:  * @return  obj .era=元号, year=元号年, month=月, date=日
 159: */
 160: function ad2era(year, month, date) {
 161:     var res = {'era':'', 'year':year, 'month':month, 'date':date };
 162:     var yyyymmdd = ('0000' + String(year)).substr(-4+ ('0000' + String(month)).substr(-2+ ('0000' + String(date)).substr(-2);
 163: 
 164:     for (e in eraTable) {
 165:         if (yyyymmdd <eraTable[e].to) {
 166:             res.era = e;
 167:             y = parseInt(String(eraTable[e].from).substr(0, 4));
 168:             res.year = year - y + 1;
 169:             break;
 170:         }
 171:     }
 172: 
 173:     return res;
 174: }

ユーザー関数 ad2era は、西暦年月日を引数とし、グローバル変数 eraTable を参照し、対応する元号・元号年月日を返す。

解説:元号を西暦年月日に変換

 176: /**
 177:  * 元号を西暦年月日に変換
 178:  * @param   obj eraset  元号年月日 .era=元号, year=元号年, month=月, date=日
 179:  * @return  obj .year=西暦年, month=月, date=日
 180: */
 181: function era2ad(eraset) {
 182:     var res = {'era':'', 'year':eraset.year, 'month':eraset.month, 'date':eraset.date };
 183:     var yyyymmdd = eraTable[eraset.era].from;
 184:     var year = parseInt(String(yyyymmdd).substr(0, 4));
 185:     res.year  = parseInt(eraset.year+ year - 1;
 186: 
 187:     return res;
 188: }

ユーザー関数 era2ad は、ad2era の逆関数である。

解説:指定した元号の年数・月数・日数

  96: /**
  97:  * 指定した元号の年数・月数・日数を返す
  98:  * @param   obj eraset  元号年月日 .era=元号, year=元号年, month=月, date=日
  99:  * @return  obj .yy=年数, mm=月数, dd=日数
 100: */
 101: function getYymmddInEra(eraset) {
 102:     //西暦年
 103:     var res = era2ad(eraset);
 104:     var year = parseInt(res.year);
 105: 
 106:     //年数
 107:     var y0 = parseInt(eraTable[eraset.era].from.substr(0, 4));
 108:     var y1 = parseInt(eraTable[eraset.era].to.substr(0, 4));
 109:     var yy = y1 - y0 + 1;
 110:     if (eraset.year > yy) {
 111:         eraset.year = 1;
 112:         var res = era2ad(eraset);
 113:         var year = parseInt(res.year);
 114:     }
 115: 
 116:     //月数
 117:     if (year == y0) {
 118:         var m0 = parseInt(eraTable[eraset.era].from.substr(4, 2));
 119:         var m1 = 12;
 120:         if (eraset.month < m0)       eraset.month = m0;
 121:     } else if (year == y1) {
 122:         var m0 = 1;
 123:         var m1 = parseInt(eraTable[eraset.era].to.substr(4, 2));
 124:         if (eraset.month > m1)      eraset.month = m1;
 125:     } else {
 126:         var m0 = 1;
 127:         var m1 = 12;
 128:     }
 129: 
 130:     //日数
 131:     var ym0 = parseInt(eraTable[eraset.era].from.substr(0, 6));
 132:     var ym1 = parseInt(eraTable[eraset.era].to.substr(0, 6));
 133:     var yymm = ('0000' + String(year)).substr(-4+ ('0000' + String(eraset.month)).substr(-2);
 134: 
 135:     var days = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
 136:     days[2] = isleap(year? 29 : 28;       //閏年の判定
 137:     if (yymm == ym0) {
 138:         var d0 = parseInt(eraTable[eraset.era].from.substr(6, 2));
 139:         var d1 = days[eraset.month];
 140:         if (eraset.date < d0)        eraset.date = d0;
 141:     } else if (yymm == ym1) {
 142:         var d0 = 1;
 143:         var d1 = parseInt(eraTable[eraset.era].to.substr(6, 2));
 144:         if (eraset.date > d1)       eraset.date = d1;
 145:     } else {
 146:         var d0 = 1;
 147:         var d1 = days[eraset.month];
 148:     }
 149: 
 150:     return {'yy':{'from':1, 'to':yy}, 'mm':{'from':m0, 'to':m1}, 'dd':{'from':d0, 'to':d1} };
 151: }

たとえば「昭和64年」を選択した場合、月は「1月」だけ、日は「1~7日」までしか選択できないようにする。
そこで、引数として元号年月日を渡すと、年・月・日の範囲を配列で返すユーザー関数が getYymmddInEra である。
同時に、閏年のときは2月29日になるようにする。

解説:年月日セレクタをつくる

 190: /**
 191:  * 年月日セレクタをつくる
 192:  * @param   obj eraset  元号年月日 .era=元号, year=元号年, month=月, date=日
 193:  * @return  int 日数/FALSE:引数の異常
 194: */
 195: function setSelector(eraset) {
 196:     res = getYymmddInEra(eraset);
 197: 
 198:     //元号セレクタ
 199:     var html = '';
 200:     for (era in eraTable) {
 201:         if (era == eraset.era)  selected = ' selected';
 202:         else                    selected = '';
 203:         html +'<option value="'+ era + '"' + selected + '>'+ era + '</option>';
 204:     }
 205:     $('#era').html(html);
 206: 
 207:     //年セレクタ
 208:     var html = '';
 209:     for (yy = res.yy.fromyy <res.yy.toyy++) {
 210:         if (yy == eraset.year)      selected = ' selected';
 211:         else                        selected = '';
 212:         if (yy == 1)    yn = '元';
 213:         else            yn = yy;
 214:         html +'<option value="'+ yy + '"' + selected + '>'+ yn + '</option>';
 215:     }
 216:     $('#year').html(html);
 217: 
 218:     //月セレクタ
 219:     var html = '';
 220:     for (mm = res.mm.frommm <res.mm.tomm++) {
 221:         if (mm == eraset.monthselected = ' selected';
 222:         else                        selected = '';
 223:         html +'<option value="'+ mm + '"' + selected + '>'+ mm + '</option>';
 224:     }
 225:     $('#month').html(html);
 226: 
 227:     //日セレクタ
 228:     var html = '';
 229:     for (dd = res.dd.fromdd <res.dd.todd++) {
 230:         if (dd == eraset.date)      selected = ' selected';
 231:         else                        selected = '';
 232:         html +'<option value="'+ dd + '"' + selected + '>'+ dd + '</option>';
 233:     }
 234:     $('#date').html(html);
 235: }

プルダウンメニューは、元号(era)、年(year)、月(month)、日(date)を別々のタグにする。
前述のユーザー関数 getYymmddInEra を呼び出し、指定された元号年の年月日をセレクタにセットする。
また、引数 eraset と合致する年月日にフォーカスをあてる(selected属性)。

解説:初期設定

  34: $(function() {
  35:     //初期値は今日の日付
  36:     var date = new Date();
  37:     //元号に変換
  38:     eraset = ad2era(date.getFullYear(), date.getMonth() + 1, date.getDate());
  39: 
  40:     //セレクタにセット
  41:     setSelector(eraset);
  42: 
  43:     //元号セレクタ変更時の動作
  44:     $('#era').change(function() {
  45:         eraset.era   = $('#era   option:selected').val();
  46:         eraset.year  = $('#year  option:selected').val();
  47:         eraset.month = $('#month option:selected').val();
  48:         eraset.date  = $('#date  option:selected').val();
  49:         setSelector(eraset);
  50:     });
  51:     //年セレクタ変更時の動作
  52:     $('#year').change(function() {
  53:         eraset.era   = $('#era   option:selected').val();
  54:         eraset.year  = $('#year  option:selected').val();
  55:         eraset.month = $('#month option:selected').val();
  56:         eraset.date  = $('#date  option:selected').val();
  57:         setSelector(eraset);
  58:     });
  59:     //月セレクタ変更時の動作
  60:     $('#month').change(function() {
  61:         eraset.era   = $('#era   option:selected').val();
  62:         eraset.year  = $('#year  option:selected').val();
  63:         eraset.month = $('#month option:selected').val();
  64:         eraset.date  = $('#date  option:selected').val();
  65:         setSelector(eraset);
  66:     });
  67: 
  68:     var refere = 'http://www.pahoo.org/e-soul/webtech/js01/js01-07-01.shtm';
  69:     $('#title').html('元号による年月日セレクタ  <span style="font-size:small;">' + getLastModified() + '版</span>');
  70:     $('#refere').html('参考サイト:<a href="' + refere +'">' + refere + '</a>');
  71: });

セレクタのID名は、元号が era、年が year、月が month、日が date とする。
また、元号・年・月・日のセレクタをつくるユーザー関数を setSelector(eraset) とする

初期設定は、ad2era 関数に今日の西暦年月日を与え、それを setSelector に渡す。
同時に、それぞれのセレクタが変更されたときに setSelector を逐次呼び出しするようセットする。

参考サイト

(この項おわり)
header