導入: なぜDate.prototype.getMonth()は注意が必要なのか
JavaScriptで日付を扱う際、必ずと言っていいほど直面するのが「月」のカウント問題です。Date.prototype.getMonth()メソッドは、標準的な直感とは異なり、1月を「0」、12月を「11」として返します。この仕様を理解していないと、APIから取得した日付を表示する際に「常に1ヶ月ずれる」というバグを頻繁に引き起こします。本記事では、この仕様を正しく理解し、現場で安全に実装するためのベストプラクティスを解説します。
基礎知識: JavaScriptのDateオブジェクトの仕組み
JavaScriptのDateオブジェクトは、内部的に1970年1月1日0時0分0秒(UTC)からの経過ミリ秒数で時間を管理しています。getMonth()メソッドは、ローカル時間における「月」を0から11の整数で返す仕様です。
なぜ0始まりなのか?その理由は、C言語のtm構造体など、古いプログラミング言語の仕様を継承しているためです。配列のインデックス(0番目=1月)としてそのまま利用できるというメリットはありますが、ユーザーインターフェース(UI)に表示する際には、必ず「+1」の補正が必要になることを忘れてはいけません。
実装/解決策: 正しい「月」の取得と表示
実装において重要なのは、「内部データ(0-11)」と「表示データ(1-12)」を明確に分離して考えることです。特にバックエンドAPIと通信する場合、APIがどちらの形式を求めているかをAPI仕様書で確認する必要があります。
サンプルプログラム: 安全な月取得とフォーマット処理
以下は、getMonth()を使って現在の月を適切に整形する実用的な関数です。
/
- 現在の日付から「1月〜12月」形式の文字列を取得する関数
応用・注意点: 現場で陥りやすいバグと回避策
1. getMonth()とsetMonth()の挙動の違い
setMonth()メソッドも同様に0始まりの数値を引数に取ります。例えば、3月を設定したい場合は「2」を渡す必要があります。ここでも混乱が生じやすいため、月を操作する際は「月数 – 1」という定型的な処理を関数化しておくことを推奨します。
2. ライブラリの検討
プロジェクトが複雑な日付計算(うるう年の考慮、タイムゾーン変換、多言語対応など)を必要とする場合、ネイティブのDateオブジェクトだけで管理するのは限界があります。現在は date-fns や Day.js といった軽量なライブラリの使用が業界標準です。これらはgetMonthの0始まり問題を隠蔽し、より宣言的な記述を可能にします。
3. バリデーションの欠如
APIから返ってきた数値をそのままgetMonthやsetMonthに渡す際は、必ず数値型であることの確認と、0〜11の範囲内であることをチェックするバリデーションを入れましょう。予期せぬ値が混入すると、Dateオブジェクトは自動的に「繰り越し(オーバーフロー)」を行い、翌月に日付がずれるといった意図しない挙動を示すことがあります。