はじめに
Webページの制作で「年」「月」「日」で入力欄が分かれているようなフォームを設置した経験がある方も多いのではないでしょうか。こうしたフォームだと「11月31日」のような存在しない日付を入力できてしまうので、「日付が正しいか」のチェックは必要不可欠です。
年 | 月 | 日 |
---|---|---|
▼ 2024 | ▼ 11 | ▼ 31 |
よくあるチェック方法の1つとして「getDate
で返る『日』が入力された値と同じか」が挙げられると思いますが、下記のようなコードの場合、ある状況下において 「正しい日付なのに誤った日付だと判定される」 事象が発生します。
// 11月に31日は存在しない
year = 2024
month = 11
date = 31
// 「2024-11-31」は「2024-12-01」扱いとなる
if (new Date(`${year}-${month}-${date}`).getDate() != date) {
// getDate()で「1」が返るためdateと一致しない
console.log('誤った日付です')
}
ローカルタイムゾーンの影響
「国内サイトに海外からアクセスした」ケースを想定します。今回はGoogle Chromeのデベロッパーツールでタイムゾーンを「サンフランシスコ(UTC-7)」に設定しコンソール上で動作を検証してみました。
すると、「2024-11-30」は正しい日付ですが、「誤った日付である」と誤判定してしまっています。
「2024-11-30」と入力しているにも関わらず、「29」が返ってきています。
getDateの仕様
JavaScriptのドキュメントには下記のように記されています。
getDate() メソッドは、地方時に基づき、指定された日付の「日」を返します。
今回挙げた例の場合、日付文字列をそのまま判定処理に渡した結果、タイムゾーンの影響を受けて意図した挙動とは違う動きとなっていました。
JavaScriptにおける日付の扱い全般に言えることですが、ブラウザや環境によって異なる解釈をされる余地が生まれないよう、タイムゾーンを明示的に指定する等の対応が必要でした。
あるいは、単に「入力された日付と同じこと」を確認したいだけならば、ローカルタイムゾーンの影響を受けない getUTCDate()
を使っても良いかもしれません。
(2025/3/24追記)
コメントでご指摘をいただきました。new Date
に日付文字列を渡して正しく解釈されると保証されているのはISO8601形式の場合だけで、このケースも「(多くのクライアントで)UTC時刻として扱われる」から結果的に合っている、というものです。
まとめ
- JavaScriptで日付を扱う際はタイムゾーンによく留意すること
- 特に、海外からもアクセスがあるようなWebサービスは要注意
参考
Date.prototype.getDate() - JavaScript | MDN
Date.prototype.getUTCDate() - JavaScript | MDN