JavaScriptで日付の差分(日数)を求める基本と実践
「2つの日時の差を“日数”で知りたい」ときは、2つのDateの差(ミリ秒)を1日のミリ秒で割るのが基本です。まず仕組みと丸め方、そしてタイムゾーンや夏時間の落とし穴を押さえましょう。
基本の考え方と式
// d1, d2 は Dateオブジェクト
const days = (d2 - d1) / (1000 * 60 * 60 * 24); // 1日は86,400,000ms
JavaScript- 返り値: 小数の「日数」。端数の扱いは目的に応じて round/ceil/floor を使います。
- 秒→日: Dateの差はミリ秒なので、1日のミリ秒 86,400,000 で割って日へ換算します。
- 基本姿勢: 「何を日数と見なすか」(経過時間か、暦日差か)を先に決める。
すぐ使えるテンプレート集
経過“日数”を小数で取得(時間差ベース)
const d1 = new Date("2025-12-01T10:00:00+09:00");
const d2 = new Date("2025-12-05T08:00:00+09:00");
const days = (d2 - d1) / (1000 * 60 * 60 * 24);
console.log(days); // 3.9166...(約3.92日)
JavaScript- ポイント: 経過時間を正確に日へ換算。端数は小数として残ります。
“差分日数”を整数で取得(丸め方を選ぶ)
const msPerDay = 1000 * 60 * 60 * 24;
const diffDaysRound = Math.round((d2 - d1) / msPerDay); // 四捨五入
const diffDaysFloor = Math.floor((d2 - d1) / msPerDay); // 切り捨て
const diffDaysCeil = Math.ceil((d2 - d1) / msPerDay); // 切り上げ
JavaScript- ポイント: 欲しい定義に合わせて丸め方を選ぶ(下の「丸めの指針」を参照)。
暦日(カレンダー日)差を安全に計算(UTCで日付丸め)
function calendarDayDiff(d1, d2) {
// UTCの“その日の0時”へそろえる(DSTやTZの影響を避ける)
const u1 = Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate());
const u2 = Date.UTC(d2.getFullYear(), d2.getMonth(), d2.getDate());
return Math.floor((u2 - u1) / (1000 * 60 * 60 * 24));
}
console.log(calendarDayDiff(new Date("2025-12-01"), new Date("2025-12-05"))); // 4
JavaScript- ポイント: 暦日差(YYYY-MM-DDどうしの差)ならUTCで日境界をそろえるのが安全。
“今日を含めて”の残り日数(包括的カウント)
function inclusiveDaysUntil(target) {
const today = new Date();
const diff = calendarDayDiff(today, target);
return diff >= 0 ? diff + 1 : diff; // 未来なら“今日を含めて”+1
}
console.log(inclusiveDaysUntil(new Date("2025-12-10"))); // 例: 今日が5日なら 6
JavaScript- ポイント: “含む/含まない”のルールを明示して足し引きする。
平日(営業日)だけ数えたい(簡易・週末除外)
function businessDays(d1, d2) {
let days = calendarDayDiff(d1, d2);
let count = 0;
for (let i = 0; i <= days; i++) {
const d = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate() + i);
const w = d.getDay(); // 0:日, 6:土
if (w !== 0 && w !== 6) count++;
}
return count;
}
console.log(businessDays(new Date("2025-12-01"), new Date("2025-12-07"))); // 5(平日のみ)
JavaScript- ポイント: 祝日は別途リスト化して除外。まずは土日除外の骨格から。
丸めの指針(目的別)
- 経過時間の“おおよそ何日?”を知りたい:
- 四捨五入: Math.round((d2 – d1) / msPerDay)
- 締切まで“あと何日残っているか”を“端数切り捨て”で知りたい:
- 切り捨て: Math.floor((d2 – d1) / msPerDay)
- “1分でも過ぎたら翌日扱い”にしたい集計など:
- 切り上げ: Math.ceil((d2 – d1) / msPerDay)
- 暦日差(12/01から12/05は常に4日)を安定させたい:
- UTCで日付丸め: calendarDayDiff を使う
よくある落とし穴と対策
- 落とし穴: DST(夏時間)で1日が24時間でない日がある
- 対策: 暦日差は UTC の「日境界」を使う(calendarDayDiff)。経過時間ベースならミリ秒差→割り算で良いが、丸めの意味を明確に。
- 落とし穴: ローカルタイムゾーンの違いで日境界がずれる
- 対策: APIや保存用は ISO(UTC)基準、表示/暦日計算は“意図したTZ”で揃える(例: Asia/Tokyo)。
- 落とし穴: “含む/含まない”が不明確で1日ズレる
- 対策: 仕様として「開始日を含むか」「終了日を含むか」を決め、+1/-1 を明示。
- 落とし穴: 時刻を含む比較で端数が出る
- 対策: 暦日計算なら対象を“その日の0時”へそろえてから差分計算。
練習問題(手を動かして覚える)
- 1. 経過日数(小数)と丸め違いを比較
const d1 = new Date("2025-12-01T10:00:00+09:00");
const d2 = new Date("2025-12-05T08:00:00+09:00");
const msPerDay = 1000 * 60 * 60 * 24;
const raw = (d2 - d1) / msPerDay;
console.log(raw, Math.floor(raw), Math.round(raw), Math.ceil(raw));
JavaScript- 2. 暦日差(UTCで安定)
console.log(calendarDayDiff(new Date("2025-12-01"), new Date("2025-12-05"))); // 4
JavaScript- 3. 今日を含めた残り日数
console.log(inclusiveDaysUntil(new Date("2025-12-10")));
JavaScript- 4. 平日だけ数える(週末除外)
console.log(businessDays(new Date("2025-12-01"), new Date("2025-12-07"))); // 5
JavaScript直感的な指針
- 経過時間の差: “ミリ秒差 ÷ 86,400,000”。丸めは目的次第。
- 暦日差を安定: UTCで日境界をそろえて計算。
- 含む/含まない: 仕様を言葉で決めて +1/-1 で調整。
- TZ/DSTの影響: 表示と保存、経過時間と暦日差を分けて考える。
