【JavaScript】「和暦を西暦に変換」って、もうやめようよ。えっ？無理？？

# 「和暦を西暦に変換」って、もうやめようよ。えっ？無理？？

👩‍🦰「ところで、あなたのおじいさんは何年生まれですか？」

🤔「昭和12年、、、」

👩‍🦰「西暦だと何年？」

🙄「さぁ？1900年くらいかなぁ？」

👩‍🦰「さすがにそれはないだろ！逆に、西暦1900年って、和暦だと何年になるの？」

😥「ちょっとまって、コード書く」

👩‍🦰（まじか、、、ググればいいのに、、、）

プログラマ泣かせの「和暦」ですが、なくなる気配はありません。あきらめましょう。

和暦を西暦に変換するコードはなら、ググれば転がっていそうですが、そもそも変換って必要なのでしょうか。

ということで、「HTML の [select] タグに西暦と和暦を併記してで選べばいいじゃん」っていうのを作りましたので、こちらに置いておきます。

# 解決策（ソリューション）がこちら

こちらが、[select] タブに西暦と和暦が併記される解決策（ソリューション😜）です。西暦で選びたい人も、和暦で選びたい人も、両方を確認しながら慎重に選びたい人も、みなさん満足いただける仕上がりになっております😁。

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="result" data-user="yamazaki3104" data-slug-hash="wvGbpzy" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="select タブに和暦を入れる JavaScript サンプル"></p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# 使い方１，select タグを準備

まず、HTML に [select] タグを用意します。
その後、JavaScript で [select] タグの [data] アトリビュートをキーにして [option] タグを挿入する仕組みです。

[select] タグの [data] アトリビュートに `data-yyyy="2000-1990"` と書くと、西暦 2000年から 1990年までの10年分の [option] タグが追加されます。
または、`data-yyyy="-10"` と書くと、今年（2020年）から10年前（2010年）までの11項目の [option] タグが追加されます。
この２つの記述をサポートしています。

[select]:https://developer.mozilla.org/ja/docs/Web/HTML/Element/select
[option]:https://developer.mozilla.org/ja/docs/Web/HTML/Element/option
[data]:https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/data-*

HTMLの記述例：

```HTML
<body>
select タブに和暦を入れる JavaScript サンプル<br/>
<form name="fm">
hu: <select name="hu" data-yyyy="2000-1900"></select><br/>
ji: <select name="ji" data-yyyy="1980-2020"></select><br/>
ko: <select name="ko" data-yyyy="-10"></select><br/>
lp: <select name="lp" data-yyyy="-20"><option selected disabled value="-">--- 西暦(和暦)
    を選択してください↓ ---</option></select><br/>
</form>

<button onclick="alert(
`hu: ${ document.forms.fm.elements.hu.value },
ji: ${ document.forms.fm.elements.ji.value },
ko: ${ document.forms.fm.elements.ko.value },
lp: ${ document.forms.fm.elements.lp.value }`
)">Check</button>
</body>
```

[form] タグや、name アトリビュートは、[button] タグの onclick で内容を確認するために使っています。ここでは本筋ではないので説明を省略させていただきます。「document.forms」ってなに？なひとは [forms] をご覧ください。

[form]:https://developer.mozilla.org/ja/docs/Web/HTML/Element/form
[button]:https://developer.mozilla.org/ja/docs/Web/HTML/Element/button
[forms]:https://developer.mozilla.org/ja/docs/Web/API/Document/forms

# 使い方２，西暦＋和暦の option を追加

次に、以下の JavaScript のコード（「西暦＋和暦」の option を追加する）を起動時に一回だけ実行します。
[script] タグに書いておけば起動時に一回だけ実行されます。

[script]:https://developer.mozilla.org/ja/docs/Web/HTML/Element/script

```HTML
<script>
/*
使い方：
１，select tag に data アトリビュート属性 data-yyyy を記述する
    例：
            <select data-yyyy="2000-1900"></select>
        or
            <select data-yyyy="-10"></select>

２，以下のコードを実行する（起動時に１回）と option tag が追加される仕組み
３，それだけ
*/
  for ( const el of document.querySelectorAll( 'select' ) )
  {
    if ( ('dataset' in el) == false ) continue
    if ( ('yyyy' in el.dataset) == false ) continue
    const yyyy = el.dataset.yyyy.split( '-' )
    if ( yyyy.length != 2 ) continue

    let last  = parseInt( yyyy[1] )
    if ( isNaN( last ) ) continue

    let start = parseInt( yyyy[0] )
    if ( isNaN( start ) ) {
      start = parseInt( (new Date()).getFullYear() )
      last  = start - last
    }

    const a = ( start > last ? -1 : 1 )
    for ( let y=start ; y != last+a ; y+= a )
    {
      const opt = document.createElement( 'option' )
      opt.setAttribute( 'value', `${ y }` )
      opt.innerText = `${ y }年`

      // 和暦を追加
      for ( const w of [
        [ '令和', 2019, 9999 ], // ←いまのところいつになるかわからないけど、書き換える必要があります
        [ '平成', 1989, 2019 ], // 平成31年
        [ '昭和', 1926, 1989 ], // 昭和64年
        [ '大正', 1912, 1926 ], // 大正15年
        [ '明治', 1868, 1912 ], // 明治45年
      ] )
      {
        if ( w[1] <= y && y <= w[2] )
          opt.innerText += ` (${ w[0] } ${ y - w[1] + 1 }年)`
      }

      el.appendChild( opt )
    }
  }
</script>
```

難しいことは、なにもしていないので、普通に読んで、メンテできるレベルと思っています。

令和がいつ終わるのかわからないので、仮に 9999 とか入れていますが。ここはメンテが必要って、わかりますよね。＜未来の自分に語りかけています。

対応しているのは、明治元年(西暦1868年)までです。明治以前の元号を知りたい方はこちら [Wikipedia 元号一覧] をご覧ください。

[Wikipedia 元号一覧]:https://ja.wikipedia.org/wiki/%E5%85%83%E5%8F%B7%E4%B8%80%E8%A6%A7_(%E6%97%A5%E6%9C%AC)


ちなみに、このサイト↓で minifi したコードも置いておきます。（動作は未確認です😜）
https://javascript-minifier.com/

```JS
for(const el of document.querySelectorAll("select")){if("dataset"in el==0)continue;if("yyyy"in el.dataset==0)continue;const e=el.dataset.yyyy.split("-");if(2!=e.length)continue;let t=parseInt(e[1]);if(isNaN(t))continue;let n=parseInt(e[0]);isNaN(n)&&(t=(n=parseInt((new Date).getFullYear()))-t);const l=n>t?-1:1;for(let e=n;e!=t+l;e+=l){const t=document.createElement("option");for(const w of(t.setAttribute("value",`${e}`),t.innerText=`${e}年`,[["令和",2019,9999],["平成",1989,2019],["昭和",1926,1989],["大正",1912,1926],["明治",1868,1912]]))w[1]<=e&&e<=w[2]&&(t.innerText+=` (${w[0]} ${e-w[1]+1}年)`);el.appendChild(t)}}
```


# おまけ（その１）和暦を西暦に変換するコード

↑では使わなかったけど副産物として、和暦を西暦に変換するコードも生まれたので、捨てずに置いておきます。

```JS
// 和暦を西暦に変換するコードも置いておきます

function create_WAREKI_to_YEAR_table()
{
    const w_tbl = {}
    const last  = parseInt( (new Date()).getFullYear() )
    for ( let y=1868 ; y <= last ; y++ )
    {
        for ( const w of [
            [ 'R', 2019, 9999 ], // 令和
            [ 'H', 1989, 2019 ], // 平成31年
            [ 'S', 1926, 1989 ], // 昭和64年
            [ 'T', 1912, 1926 ], // 大正15年
            [ 'M', 1868, 1912 ], // 明治45年
        ] )
        {
            if ( w[1] <= y && y <= w[2] )
                w_tbl[ `${ w[0] }${ y - w[1] + 1 }` ] = y
        }
    }
    return w_tbl
}

// 使い方
const wareki = create_WAREKI_to_YEAR_table()

console.log( 'R1 ->',  wareki['R1'] )
console.log( 'R2 ->',  wareki['R2'] )
console.log( 'H1 ->',  wareki['H1'] )
console.log( 'H10 ->', wareki['H10'] )
console.log( 'S1 ->',  wareki['S1'] )
console.log( 'S10 ->', wareki['S10'] )
console.log( 'T1 ->',  wareki['T1'] )
console.log( 'T10 ->', wareki['T10'] )
console.log( 'M1 ->',  wareki['M1'] )
console.log( 'M10 ->', wareki['M10'] )
```

# おまけ（その２）input lint + datalist タブ版

input lint + datalist タブ版も作ったので置いて置きます。
結局は好みの問題だと思うけど、キーボードから入力するのなら、オートコンプリート機能のあるこっちのほうがいいのかな🙄。

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="html,result" data-user="yamazaki3104" data-slug-hash="oNxrxop" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="input lint + datalist タブに和暦を入れる JavaScript サンプル"></p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

それでは、みなさまのプログラミングライフを応援しています😉（なにそれ😁）。