Edited at

ワンライナーでゴリ押し元号対応に挑戦してみる


免責

※ ポエムたっぷりネタ記事です。(念の為)


はじめに

2019年5月1日より、新元号になるようです。

世の中のIT系企業はそれに向けてザワついてますね。弊社もそうです。

もし、明日までに元号対応してくれ、と言われたら、あなたならどうしますか?

という仮定の下、ワンライナーでアドホック問題解決をするべく立ち上がり、そして、とりあえず明日の方向に向かって走り出したところ

JavaScriptの落とし穴にハマったので、それを書き留めることにします。


とりあえず実装

動作環境:Google Chrome(71.0.3578.98(Official Build) (64 ビット))

<html>

<body>
平成32年
</body>
</html>

↑のようなHTMLがあったとした場合に、JavaScriptで平成○○ → 新元号○○と置換したいと思います。


  • 非同期で読み込んだ内容は置き換わらないんじゃないか

  • 更に次の年号の時にどう実装するのか

  • 読み込み時に一瞬、旧元号が表示されるんじゃないか

  • 元年表記できないじゃないか

みたいなツッコミを数多く思いつくことができる人が頭のいい人だってばっちゃんが言って(ry

それでは、本題です。


  1. body内の文字を全て取得する

    image.png


  2. 平成○○年という表記を探して、新元号に置換

    image.png


  3. ひとまず30を引いてみる

    image.png


ん???

なぜNaNになっているんだ?

$1で"32"という文字列が取れているはずなんだが、、、引き算すればええんちゃうんか???


いろいろ調べた結果

結論からいうと、replace関数の挙動というか、JavaScriptを全然理解できていませんでした。

知見その1

どうやら、replace関数の中で第1引数の文字列から、$1という文字列を探して置換しているっぽい

例えば、substringしてみたところ、以下のような挙動である。

image.png

知見その2

文字列の$1ではなく、RegExp.$1みたいな感じで指定すれば、計算されるっぽい

image.png

ただし、gオプションをつけた場合は、期待した動作はしなかった、、、

知見その3

replace関数にgオプションをつける場合は、第二引数にコールバック関数を渡す必要があるっぽい => 参考

知見その4

というか、\$1~\$9で指定する方法は、非推奨っぽい => ドキュメント

image.png


成果物

というわけで、、、、

その後も紆余曲折ありましたが、一応、元号対応ワンライナーができました。

document.body.innerText = document.body.innerText.replace(/(平成)([ | ]*)([0-9]+)/g, function(f,s1,s2,s3){return parseInt(s3) > 31 ? '新元号' + s2 + (parseInt(s3) - 30) : s1 + s2 + s3})

全角数字に対応すると、流石にワンライナーではアレなので、普通に書きました。

漢数字は対応しません。敢えてね。

あと、半角数字をcharCodeAtして引き算すると半角になるのは初知りでした

const convertHalfStr = function(fullStr) {

let halfStr = '';

fullStr.split('').forEach(function(s){
halfStr += String.fromCharCode(s.charCodeAt(0) - 65248);
});
return halfStr;
}

const convertEraName = function(f, s1, s2, s3) {
if(s3.match(/[0-9]/) !== null) {
s3 = convertHalfStr(s3);
}
return parseInt(s3) > 31 ? '新元号' + s2 + (parseInt(s3) - 30) : s1 + s2 + s3;
}

document.body.innerText = document.body.innerText.replace(/(平成)([ | ]*)([0-9|0-9]+)/g, convertEraName);


感想


  • JavaScriptは時間泥棒

  • でも好き