なんでやねん。 pic.twitter.com/WGWqTjiVkN
— みぎ (@migi) March 29, 2018
原因
原因をちょっと調べてみた。
new Date(dateString)の説明としてこんなものが。
日付を表す文字列値です。文字列は Date.parse() メソッドによる認識可能な形式でなければなりません (IETF 準拠の RFC 2822 timestamps および ISO8601 版 参照)。
なるほど。
内部でDate.parse()が走っていると。
Date.parse()については、みなさんご存知のとおりブラウザによって動作が不安定なので使わないほうが良いやつ。
Date.parse() - JavaScript | MDN
ES5 に準拠して実装されるまで Date.parse の使用は推奨されません。
ということで、new Date()の引数として、文字列を渡すこと自体やめた方が良いようですね。。
というか、上記のnew Date(dateString)の説明の直下にそもそもちゃんと書いてあったし。
注記: ブラウザごとに動作が異なり一貫性がないため、Date コンストラクタ (または同等の Date.parse) で日付文字列を解釈しないように強くすすめます。
対処法
とは言え、APIで帰ってきた日付がYYYY-MM-DDで固定されていてそれを使わなきゃいけない、って状況は多そう。
APIを修正してわざわざ{year: 2018, month: 12, day: 23}みたいにするのもモヤッとするし。
対処法 A
文字列YYYY-MM-DDから年月日それぞれの値を取り出して数値化してnew Date(year, month, day)の形で渡す。
たぶんこれが一番正確。
取り出すのも数値化するのも一手間かかってめんどくさいけど。
YYYY-M-D的な形だったら文字の位置からは取り出せないので正規表現使う必要もあるし。
めんどくさい。
でも正確で安定はしそう。
対処法 B
文字列YYYY-MM-DDを文字列YYYY/MM/DDに変換してnew Date(dateString)の形で渡す。
相変わらずnew Date(dateString)を使っちゃってるけど。
でもどうやらYYYY-MM-DDに比べてYYYY/MM/DDだと安定感は増すっぽい。
なんでや。
これだと-を/に変換するだけなので面倒さはほぼ無い。
なんかもっと良い方法を知っている人がいれば教えてください……。
