ウェブエンジニア問題集

日付と時刻の操作 — Dateの生成・フォーマット・差分計算と月0始まりの罠

「投稿日時を表示する」「予約の何日前か計算する」「今日の日付でファイル名を作る」——日付の処理はほぼすべてのアプリで登場します。Date は便利な反面、月が0から始まるなどの独特な落とし穴があり、初心者がつまずく定番分野でもあります。

この章では、Date の生成から各要素の取り出し、表示用のフォーマット、差分・加算の計算、そしてタイムゾーンの注意点までを、引数つきの表で逆引きできるように整理します。

Date オブジェクトとは — 現在時刻の取得

Date は「ある一点の日時」を表す組み込みオブジェクトです。内部的には1970年1月1日(UTC)からの経過ミリ秒という1つの数値で時刻を保持しています。

const now = new Date(); // 現在の日時
console.log(now); // 例: 2026-06-06T...(実行した瞬間の日時)
 
Date.now(); // 例: 1781049600000(現在のミリ秒。数値だけが欲しいとき)
日付や予定を扱うイメージ

Date の作り方 — 引数で挙動が変わる

new Date() は渡す引数によって意味が変わります。ここが最初の関門です。

構文: new Date(...)

渡し方引数生成される日時
new Date()なし現在の日時
new Date(ms)ms:1970年からのミリ秒そのミリ秒に対応する日時
new Date(dateString)dateString:日付文字列文字列を解釈した日時('2026-06-06' など)
new Date(year, monthIndex, day, ...)年・月(0始まり)・日・時・分・秒各要素を指定した日時
new Date(0); // 1970-01-01T00:00:00.000Z(基準点)
new Date('2026-06-06'); // ISO形式の文字列から
new Date(2026, 5, 6); // 2026年6月6日(※月は 5 で6月!)
学習者学習者

new Date(2026, 5, 6) が6月…?5 を渡したのに6月になるの、絶対バグらせる自信ある…。

最大の罠 — 月は「0始まり」

Date の月は 0〜11で表されます。0が1月、11が12月です。日(day)や年は通常どおりなのに、月だけ0始まりという非対称さが混乱の元です。

const d = new Date(2026, 0, 1); // 2026年1月1日(0 = 1月)
const d2 = new Date(2026, 11, 31); // 2026年12月31日(11 = 12月)

日付の各要素を取り出す

生成した Date から年・月・日などを取り出すメソッド群です。いずれも引数なしで、数値を返します。

メソッド戻り値
date.getFullYear()年(4桁。getYear() は使わない)
date.getMonth()月(0〜11。表示時は +1
date.getDate()日(1〜31)
date.getDay()曜日(0=日曜 〜 6=土曜
date.getHours()時(0〜23)
date.getMinutes()分(0〜59)
date.getSeconds()秒(0〜59)
date.getTime()1970年からのミリ秒(差分計算に使う)
const d = new Date(2026, 5, 6, 14, 30); // 2026-06-06 14:30
 
d.getFullYear(); // 2026
d.getMonth() + 1; // 6(+1して人間が読む月に)
d.getDate(); // 6
d.getHours(); // 14
先生先生

getDay()(曜日)と getDate()(日にち)は名前が紛らわしいから要注意。「Dayは曜日、Dateは日にち」とセットで覚えよう。

フォーマット — 表示用の文字列にする

日本語の「2026年6月6日」や「6/6 14:30」のような表示は、要素を1つずつ組み立てなくても専用メソッドで作れます。

ロケールに合わせて整形 — toLocaleString 系

構文: date.toLocaleDateString(locales?, options?)

引数説明
locales(省略可)言語・地域('ja-JP' など)。省略すると実行環境の設定
options(省略可)表示形式({ year: 'numeric', month: 'long', day: 'numeric' } など)

戻り値: その地域の慣習で整形した文字列

const d = new Date(2026, 5, 6, 14, 30);
 
d.toLocaleDateString('ja-JP'); // "2026/6/6"
d.toLocaleString('ja-JP'); // "2026/6/6 14:30:00"(日付+時刻)
 
d.toLocaleDateString('ja-JP', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  weekday: 'long',
}); // "2026年6月6日土曜日"

機械可読な形式 — toISOString

構文: date.toISOString()(引数なし)

戻り値: "2026-06-06T05:30:00.000Z" のようなISO 8601形式の文字列(UTC)

new Date(2026, 5, 6).toISOString(); // "2026-06-05T15:00:00.000Z"

日付の計算 — 差分と加算

差分(何日・何時間離れているか)

getTime() でミリ秒に変換し、引き算してから単位を割り戻します。

const start = new Date(2026, 5, 1);
const end = new Date(2026, 5, 6);
 
const diffMs = end.getTime() - start.getTime(); // ミリ秒の差
const diffDays = diffMs / (1000 * 60 * 60 * 24); // 5(日数に変換)
学習者学習者

1000 * 60 * 60 * 24 って何の数字…?毎回これ書くの大変そう。

これは「1日 = 1000ミリ秒 × 60秒 × 60分 × 24時間」を表す定数です。前章の数値の扱いで見たとおり、Date の正体はミリ秒という数値なので、引き算が日数計算になります。頻繁に書くなら定数化するか、後述のライブラリに任せます。

加算(◯日後・◯時間後)

setDate() などのセッターで日付を進められます。setDate(getDate() + 7) のように現在値に足すのが基本です。月をまたぐ繰り上がりも自動でやってくれます。

const d = new Date(2026, 5, 6);
d.setDate(d.getDate() + 7); // 7日後(6/13)
// 6/28 に +7 すれば自動で 7/5 になる(月またぎも処理される)

タイムゾーンの注意点

Date は「内部はUTC(協定世界時)の絶対時刻、表示や getHours() などはローカルタイムゾーン」という二面性を持ちます。

  • toISOString() の末尾 ZUTC を意味する
  • getHours() などのゲッターは実行環境のローカル時刻を返す
  • 日付だけの文字列 '2026-06-06'UTCの0時として解釈され、日本(+9時間)で表示すると意図とずれることがある
// 環境のタイムゾーンによって結果が変わりうる
new Date('2026-06-06').getDate(); // 日本だと 6 になるとは限らない

サーバーとブラウザでタイムゾーンが異なる、夏時間がある、といった条件が絡むと一気に複雑になります。時刻の厳密さが必要なシステムでは、UTCで保存し表示時に変換するのが基本方針です。

これからの選択肢 — Temporal とライブラリ

早見表

やりたいこと使うもの
現在日時new Date() / Date.now()(ミリ秒)
年・日を取得getFullYear() / getDate()
月を取得(人間向け)getMonth() + 1
曜日を取得getDay()(0=日〜6=土)
「2026年6月6日」表示toLocaleDateString('ja-JP', {...})
保存・送信用の文字列toISOString()
日数の差分(d2 - d1) / (1000*60*60*24)
◯日後d.setDate(d.getDate() + n)(破壊的)

よくあるハマりどころ

日付処理のハマりどころを確認するイメージ

1. 月が0始まり

最頻出の罠。new Date(2026, 5, 6) は6月。生成時は「実際の月 − 1」、getMonth() の結果は「+1」で人間の月に直します。

2. getDay()getDate() を取り違える

getDay() は曜日(0〜6)、getDate() は日にち(1〜31)。名前が似ているので逆に使いがちです。

3. セッターが元の日付を壊す

setDate などは破壊的。元の値を残すなら const copy = new Date(original) してから操作します。

4. 文字列のパースは形式依存

new Date('2026/06/06')new Date('June 6, 2026') は環境によって解釈が異なることがあります。'2026-06-06' のISO形式が最も安全です。非標準の形式を渡すと Invalid Date になることもあります。

new Date('2026-06-06'); // OK(ISO形式)
new Date('06-06-2026'); // 環境依存。避ける

ちゃんと使うためのポイント

  • Date の正体は「1970年からのミリ秒」という1つの数値。だから差分は引き算で出せる
  • 月は0始まり(0=1月)。生成は −1、getMonth() は +1
  • getDay()=曜日、getDate()=日にち。混同しない
  • 表示は toLocaleString 系、保存・送信は toISOString()
  • セッター(setDate など)は破壊的。コピーしてから操作する
  • タイムゾーンが絡む厳密な処理や複雑な計算は、Day.js / date-fns などのライブラリに任せる

次の章では、JSONの基礎と実践 を扱います。APIとデータをやり取りするとき、DateJSON.stringify するとどうなるか——という落とし穴もあわせて見ていきます。