「あと何日」「何時間前」「年齢は何歳」など、2 つの日時の差分を計算する処理は Web 開発で頻出します。JavaScript では Date オブジェクト同士の減算でミリ秒の差分が得られ、そこから日数・時間・分・秒に変換できます。この記事ではミリ秒ベースの基本から、月差分・年齢計算・相対表示(「3日前」)まで体系的に解説します。
・2 つの Date の差分をミリ秒で取得する方法
・ミリ秒を日数・時間・分・秒に変換する方法
・月の差分・年の差分の計算
・年齢計算(誕生日から現在まで)
・相対表示(「3 日前」「2 時間後」)のフォーマット
・Intl.RelativeTimeFormat による国際化対応
・performance.now() による経過時間計測
・夏時間・タイムゾーンの注意点
ミリ秒単位で差分を取得する
Date オブジェクト同士は減算演算子で直接計算でき、結果はミリ秒で返ります。
const date1 = new Date("2026-03-01T10:00:00");
const date2 = new Date("2026-04-15T18:30:00");
const diffMs = date2 - date1;
console.log(diffMs); // 3902600000(ミリ秒)
このミリ秒をもとに、日・時間・分・秒に変換していきます。
変換に使う定数
| 単位 | 1単位あたりのミリ秒 | 定数 |
|---|---|---|
| 1 秒 | 1,000 | 1000 |
| 1 分 | 60,000 | 1000 * 60 |
| 1 時間 | 3,600,000 | 1000 * 60 * 60 |
| 1 日 | 86,400,000 | 1000 * 60 * 60 * 24 |
日数・時間・分・秒に変換する
単一の単位に変換する
const diffMs = new Date("2026-04-15") - new Date("2026-03-01");
// 日数
const days = Math.floor(diffMs / (1000 * 60 * 60 * 24));
console.log(days); // 45
// 時間数
const hours = Math.floor(diffMs / (1000 * 60 * 60));
console.log(hours); // 1080
// 分数
const minutes = Math.floor(diffMs / (1000 * 60));
console.log(minutes); // 64800
日・時間・分・秒に分解する
function dateDiff(start, end) {
const ms = Math.abs(end - start);
const days = Math.floor(ms / (1000 * 60 * 60 * 24));
const hours = Math.floor((ms % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((ms % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((ms % (1000 * 60)) / 1000);
return { days, hours, minutes, seconds };
}
const result = dateDiff(
new Date("2026-03-31T10:00:00"),
new Date("2026-04-02T15:30:45")
);
console.log(result);
// { days: 2, hours: 5, minutes: 30, seconds: 45 }
// フォーマットして表示
console.log(`${result.days}日${result.hours}時間${result.minutes}分${result.seconds}秒`);
// "2日5時間30分45秒"
Math.abs() で絶対値を取ることで、start と end の順序に関係なく正の差分が得られます。月の差分・年の差分を計算する
月や年の差分はミリ秒の単純な割り算では計算できません(月の日数は 28〜31 日で一定でないため)。年・月の各コンポーネントを使って計算します。
function monthDiff(start, end) {
return (end.getFullYear() - start.getFullYear()) * 12
+ (end.getMonth() - start.getMonth());
}
console.log(monthDiff(
new Date("2025-06-15"),
new Date("2026-03-20")
)); // 9
function yearDiff(start, end) {
return end.getFullYear() - start.getFullYear();
}
console.log(yearDiff(
new Date("2020-01-01"),
new Date("2026-03-31")
)); // 6
differenceInMonths などライブラリの利用を検討してください。年齢を計算する(誕生日から現在まで)
function calcAge(birthday) {
const today = new Date();
let age = today.getFullYear() - birthday.getFullYear();
// 今年の誕生日がまだ来ていなければ -1
const monthDiff = today.getMonth() - birthday.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthday.getDate())) {
age--;
}
return age;
}
console.log(calcAge(new Date("1990-08-15"))); // 35(2026年3月時点)
console.log(calcAge(new Date("2000-12-25"))); // 25(2026年3月時点)
相対表示(「3 日前」「2 時間後」)にフォーマットする
SNS やブログでよく見る「3 日前」「たった今」のような表示を実装します。
function timeAgo(date) {
const now = new Date();
const diffMs = now - date;
const diffSec = Math.floor(diffMs / 1000);
const diffMin = Math.floor(diffSec / 60);
const diffHour = Math.floor(diffMin / 60);
const diffDay = Math.floor(diffHour / 24);
const diffMonth = Math.floor(diffDay / 30);
const diffYear = Math.floor(diffDay / 365);
if (diffSec < 60) return "たった今";
if (diffMin < 60) return `${diffMin}分前`;
if (diffHour < 24) return `${diffHour}時間前`;
if (diffDay < 30) return `${diffDay}日前`;
if (diffMonth < 12) return `${diffMonth}ヶ月前`;
return `${diffYear}年前`;
}
// 使用例
console.log(timeAgo(new Date(Date.now() - 3 * 60 * 1000))); // "3分前"
console.log(timeAgo(new Date(Date.now() - 5 * 24 * 3600000))); // "5日前"
Intl.RelativeTimeFormat で国際化対応する
手動で「〇日前」を組み立てる代わりに、Intl.RelativeTimeFormat を使うとロケールに応じた相対表示が自動生成されます。
const rtf = new Intl.RelativeTimeFormat("ja", { numeric: "auto" });
console.log(rtf.format(-1, "day")); // "昨日"
console.log(rtf.format(-3, "day")); // "3 日前"
console.log(rtf.format(1, "hour")); // "1 時間後"
console.log(rtf.format(-2, "month")); // "2 か月前"
console.log(rtf.format(0, "day")); // "今日"
| numeric オプション | 0 の場合 | -1 の場合 |
|---|---|---|
"always"(デフォルト) |
“0 日前” | “1 日前” |
"auto" |
“今日” | “昨日” |
numeric: "auto" を指定すると「昨日」「今日」「明日」のような自然な表現になります。処理の経過時間を計測する(performance.now)
日付の差分ではなく、コードの実行時間を計測するには performance.now() を使います。Date よりも高精度(マイクロ秒単位)です。
const start = performance.now();
// 計測したい処理
const arr = Array.from({ length: 100000 }, (_, i) => i);
arr.sort(() => Math.random() - 0.5);
const end = performance.now();
console.log(`実行時間: ${(end - start).toFixed(2)}ms`);
// "実行時間: 42.35ms"
| 方法 | 精度 | 用途 |
|---|---|---|
Date.now() |
ミリ秒 | 日時の差分(日・時間・分) |
performance.now() |
マイクロ秒 | 処理速度の計測(ベンチマーク) |
夏時間・タイムゾーンの注意点
日数の差分を diffMs / 86400000 で計算すると、夏時間(DST)切り替えのある地域では誤差が発生する場合があります。
// 夏時間切り替え日をまたぐ場合(米国の例)
const d1 = new Date("2026-03-08T00:00:00"); // DST開始前
const d2 = new Date("2026-03-09T00:00:00"); // DST開始後
// 実際には23時間しか経過していないため
// (d2 - d1) / 86400000 = 0.9583... → Math.floor で 0日になる可能性
Date.UTC() を使う)か、date-fns-tz などの TZ 対応ライブラリを利用してください。関連記事
- 日付を操作する方法 — 加算・減算・比較・月末取得
- 日付を取得する方法 — Date オブジェクト・年月日時分秒・フォーマット
- 日付のフォーマットを変換する方法
- setInterval の使い方 — カウントダウンタイマーの実装
- カウントダウンタイマーの作成
- Intl API を使った日付・数値の国際化フォーマット
よくある質問
Math.floor((date2 - date1) / (1000 * 60 * 60 * 24)) で日数が得られます。Date オブジェクト同士の減算はミリ秒を返すので、1 日のミリ秒数(86,400,000)で割ります。(endYear - startYear) * 12 + (endMonth - startMonth) のように年・月のコンポーネントで計算します。Intl.RelativeTimeFormat を使えば、rtf.format(-3, "day") で "3 日前" が自動生成されます。ロケールを変えるだけで英語やその他の言語にも対応できます。Date.now()、コードの実行速度の計測(ベンチマーク)には performance.now() を使います。performance.now() はマイクロ秒精度で、ページ読み込みからの経過時間を返します。Math.floor の結果がずれることがあります。日本は夏時間がないため影響を受けませんが、グローバル対応では UTC ベースの計算か TZ 対応ライブラリを使ってください。まとめ
JavaScript で日時の差分を計算する方法を整理しました。
- 基本:
date2 - date1でミリ秒差分を取得し、日・時間・分・秒に変換 - 月差分: 年×12 + 月で計算(ミリ秒の割り算では不可)
- 年齢計算: 年の差分 + 誕生日が過ぎたかの判定
- 相対表示:
Intl.RelativeTimeFormatで「3日前」「昨日」を自動生成 - 計測: 処理速度には
performance.now()を使用
日数や時間の差分はミリ秒ベースの計算でシンプルに実装できますが、月差分や年齢計算は個別のロジックが必要です。SNS のような相対表示には Intl.RelativeTimeFormat が便利なので、ぜひ活用してください。