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

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

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

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

プログラムの目標

PHPで元号年月日入力

解説:元号の開始と終了

0025: //元号=西暦一覧
0026: var eraTable = {
0027:     '明治'  : {'from':'18680125', 'to':'19120729'},
0028:     '大正'  : {'from':'19120730', 'to':'19261224'},
0029:     '昭和'  : {'from':'19261225', 'to':'19890107'},
0030:     '平成'  : {'from':'19890108', 'to':'20190430'},
0031:     '令和'  : {'from':'20190501', 'to':'29991231'}
0032: };

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

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

0153: /**
0154:  * 西暦年月日を元号に変換
0155:  * @param int year  西暦年
0156:  * @param int month月
0157:  * @param int date  日
0158:  * @return obj .era=元号, year=元号年, month=月, date=日
0159: */
0160: function ad2era(yearmonthdate) {
0161:     var res = {'era':'', 'year':year, 'month':month, 'date':date };
0162:     var yyyymmdd = ('0000' + String(year)).substr(-4) + ('0000' + String(month)).substr(-2) + ('0000' + String(date)).substr(-2);
0163: 
0164:     for (e in eraTable) {
0165:         if (yyyymmdd <= eraTable[e].to) {
0166:             res.era = e;
0167:             y = parseInt(String(eraTable[e].from).substr(0, 4));
0168:             res.year = year - y + 1;
0169:             break;
0170:         }
0171:     }
0172: 
0173:     return res;
0174: }

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

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

0176: /**
0177:  * 元号を西暦年月日に変換
0178:  * @param obj eraset  元号年月日 .era=元号, year=元号年, month=月, date=日
0179:  * @return obj .year=西暦年, month=月, date=日
0180: */
0181: function era2ad(eraset) {
0182:     var res = {'era':'', 'year':eraset.year, 'month':eraset.month, 'date':eraset.date };
0183:     var yyyymmdd = eraTable[eraset.era].from;
0184:     var year = parseInt(String(yyyymmdd).substr(0, 4));
0185:     res.year  = parseInt(eraset.year) + year - 1;
0186: 
0187:     return res;
0188: }

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

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

0096: /**
0097:  * 指定した元号の年数・月数・日数を返す
0098:  * @param obj eraset  元号年月日 .era=元号, year=元号年, month=月, date=日
0099:  * @return obj .yy=年数, mm=月数, dd=日数
0100: */
0101: function getYymmddInEra(eraset) {
0102:     //西暦年
0103:     var res = era2ad(eraset);
0104:     var year = parseInt(res.year);
0105: 
0106:     //年数
0107:     var y0 = parseInt(eraTable[eraset.era].from.substr(0, 4));
0108:     var y1 = parseInt(eraTable[eraset.era].to.substr(0, 4));
0109:     var yy = y1 - y0 + 1;
0110:     if (eraset.year > yy) {
0111:         eraset.year = 1;
0112:         var res = era2ad(eraset);
0113:         var year = parseInt(res.year);
0114:     }
0115: 
0116:     //月数
0117:     if (year == y0) {
0118:         var m0 = parseInt(eraTable[eraset.era].from.substr(4, 2));
0119:         var m1 = 12;
0120:         if (eraset.month < m0)       eraset.month = m0;
0121:     } else if (year == y1) {
0122:         var m0 = 1;
0123:         var m1 = parseInt(eraTable[eraset.era].to.substr(4, 2));
0124:         if (eraset.month > m1)       eraset.month = m1;
0125:     } else {
0126:         var m0 = 1;
0127:         var m1 = 12;
0128:     }
0129: 
0130:     //日数
0131:     var ym0 = parseInt(eraTable[eraset.era].from.substr(0, 6));
0132:     var ym1 = parseInt(eraTable[eraset.era].to.substr(0, 6));
0133:     var yymm = ('0000' + String(year)).substr(-4) + ('0000' + String(eraset.month)).substr(-2);
0134: 
0135:     var days = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
0136:     days[2] = isleap(year) ? 29 : 28;       //閏年の判定
0137:     if (yymm == ym0) {
0138:         var d0 = parseInt(eraTable[eraset.era].from.substr(6, 2));
0139:         var d1 = days[eraset.month];
0140:         if (eraset.date < d0)        eraset.date = d0;
0141:     } else if (yymm == ym1) {
0142:         var d0 = 1;
0143:         var d1 = parseInt(eraTable[eraset.era].to.substr(6, 2));
0144:         if (eraset.date > d1)        eraset.date = d1;
0145:     } else {
0146:         var d0 = 1;
0147:         var d1 = days[eraset.month];
0148:     }
0149: 
0150:     return {'yy':{'from':1, 'to':yy}, 'mm':{'from':m0, 'to':m1}, 'dd':{'from':d0, 'to':d1} };
0151: }

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

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

0190: /**
0191:  * 年月日セレクタをつくる
0192:  * @param obj eraset  元号年月日 .era=元号, year=元号年, month=月, date=日
0193:  * @return int日数/FALSE:引数の異常
0194: */
0195: function setSelector(eraset) {
0196:     res = getYymmddInEra(eraset);
0197: 
0198:     //元号セレクタ
0199:     var html = '';
0200:     for (era in eraTable) {
0201:         if (era == eraset.era)   selected = ' selected';
0202:         else                    selected = '';
0203:         html += '<option value="'+ era + '"' + selected + '>'+ era + '</option>';
0204:     }
0205:     $('#era').html(html);
0206: 
0207:     //年セレクタ
0208:     var html = '';
0209:     for (yy = res.yy.fromyy <= res.yy.toyy++) {
0210:         if (yy == eraset.year)       selected = ' selected';
0211:         else                        selected = '';
0212:         if (yy == 1)    yn = '';
0213:         else            yn = yy;
0214:         html += '<option value="'+ yy + '"' + selected + '>'+ yn + '</option>';
0215:     }
0216:     $('#year').html(html);
0217: 
0218:     //月セレクタ
0219:     var html = '';
0220:     for (mm = res.mm.frommm <= res.mm.tomm++) {
0221:         if (mm == eraset.month)  selected = ' selected';
0222:         else                        selected = '';
0223:         html += '<option value="'+ mm + '"' + selected + '>'+ mm + '</option>';
0224:     }
0225:     $('#month').html(html);
0226: 
0227:     //日セレクタ
0228:     var html = '';
0229:     for (dd = res.dd.fromdd <= res.dd.todd++) {
0230:         if (dd == eraset.date)       selected = ' selected';
0231:         else                        selected = '';
0232:         html += '<option value="'+ dd + '"' + selected + '>'+ dd + '</option>';
0233:     }
0234:     $('#date').html(html);
0235: }

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

解説:初期設定

0034: $(function() {
0035:     //初期値は今日の日付
0036:     var date = new Date();
0037:     //元号に変換
0038:     eraset = ad2era(date.getFullYear(), date.getMonth() + 1, date.getDate());
0039: 
0040:     //セレクタにセット
0041:     setSelector(eraset);
0042: 
0043:     //元号セレクタ変更時の動作
0044:     $('#era').change(function() {
0045:         eraset.era   = $('#era   option:selected').val();
0046:         eraset.year  = $('#year  option:selected').val();
0047:         eraset.month = $('#month option:selected').val();
0048:         eraset.date  = $('#date  option:selected').val();
0049:         setSelector(eraset);
0050:     });
0051:     //年セレクタ変更時の動作
0052:     $('#year').change(function() {
0053:         eraset.era   = $('#era   option:selected').val();
0054:         eraset.year  = $('#year  option:selected').val();
0055:         eraset.month = $('#month option:selected').val();
0056:         eraset.date  = $('#date  option:selected').val();
0057:         setSelector(eraset);
0058:     });
0059:     //月セレクタ変更時の動作
0060:     $('#month').change(function() {
0061:         eraset.era   = $('#era   option:selected').val();
0062:         eraset.year  = $('#year  option:selected').val();
0063:         eraset.month = $('#month option:selected').val();
0064:         eraset.date  = $('#date  option:selected').val();
0065:         setSelector(eraset);
0066:     });
0067: 
0068:     var refere = 'https://www.pahoo.org/e-soul/webtech/js01/js01-07-01.shtm';
0069:     $('#title').html('元号による年月日セレクタ  <span style="font-size:small;">' + getLastModified() + '版</span>');
0070:     $('#refere').html('参考サイト:<a href="' + refere +'">' + refere + '</a>');
0071: });

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

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

参考サイト

(この項おわり)
header