JavaScriptのDateで日付を比較する - 初心者向け基本ガイド
JavaScriptのDateオブジェクトを使った日付比較を初心者向けに詳しく解説。基本的な比較方法から実践的な応用例まで、日付処理をマスターするための重要な知識を分かりやすく紹介します。
JavaScriptで日付の処理をしたいと思ったことはありませんか?
「今日が締切日を過ぎているかチェックしたい」「どちらの日付が新しいか判定したい」「イベントの開催日まであと何日か計算したい」
こんな場面って、プログラミングをしていると必ず出てきますよね。
実は、JavaScriptにはDateオブジェクトという便利な機能があって、日付の比較がとても簡単にできるんです。 一度覚えてしまえば、期限管理やスケジュール機能など、実用的なアプリケーションが作れるようになりますよ。
この記事では、JavaScript初心者向けにDateオブジェクトを使った日付比較の方法を詳しく解説します。 基本的な使い方から実践的な応用例まで、一緒に学んでいきましょう!
Dateオブジェクトって何?基本を理解しよう
JavaScriptの日付管理システム
Dateオブジェクトは、JavaScriptで日付と時刻を扱うための特別な機能です。 年、月、日、時、分、秒、ミリ秒の情報をまとめて管理してくれます。
簡単に言うと、「日付のための便利な道具箱」みたいなものですね。
// 現在の日時を取得let now = new Date();console.log("現在の日時:", now);
// 特定の日付を作成let specificDate = new Date("2025-01-15");console.log("特定の日付:", specificDate);
// 年、月、日を指定して作成(月は0から始まることに注意)let customDate = new Date(2025, 0, 15); // 2025年1月15日console.log("カスタム日付:", customDate);
このコードでは、3つの方法でDateオブジェクトを作っています。
new Date()
で現在の日時を取得できます。
new Date("2025-01-15")
で特定の日付を指定できます。
new Date(2025, 0, 15)
で年月日を個別に指定することもできますね。
ここで注意が必要なのは、月の指定です。 JavaScriptでは月が0から始まるので、1月は0、2月は1という具合になっています。
Dateオブジェクトの特徴を知ろう
Dateオブジェクトには、とても便利な特徴があります。
- ミリ秒単位で管理:1970年1月1日からの経過ミリ秒で計算
- タイムゾーンを考慮:お住まいの地域の時刻で表示
- 比較演算子が使える:<、>、<=、>=で直接比較可能
- 計算ができる:日数の差や加算減算が可能
// ミリ秒値の確認let date1 = new Date("2025-01-01");let date2 = new Date("2025-01-02");
console.log("date1のミリ秒値:", date1.getTime());console.log("date2のミリ秒値:", date2.getTime());console.log("差分(ミリ秒):", date2.getTime() - date1.getTime());console.log("差分(日):", (date2.getTime() - date1.getTime()) / (1000 * 60 * 60 * 24));
getTime()
メソッドで、ミリ秒値を取得できます。
この値を使って、日数の差分なども計算できるんです。
1日は24時間×60分×60秒×1000ミリ秒なので、86400000ミリ秒になります。
基本的な日付比較をマスターしよう
比較演算子で簡単比較
Dateオブジェクトは、普通の数字と同じように比較演算子が使えます。 これがとても便利なんです。
// 日付の作成let date1 = new Date("2025-01-10");let date2 = new Date("2025-01-15");let date3 = new Date("2025-01-10");
// 基本的な比較console.log("date1 < date2:", date1 < date2); // trueconsole.log("date1 > date2:", date1 > date2); // falseconsole.log("date1 <= date3:", date1 <= date3); // trueconsole.log("date1 >= date3:", date1 >= date3); // true
// 等価比較(注意が必要)console.log("date1 == date3:", date1 == date3); // false(オブジェクト参照が異なる)console.log("date1 === date3:", date1 === date3); // false(オブジェクト参照が異なる)
<
や>
での比較は、直感的でとても分かりやすいですね。
date1がdate2より小さい(古い)ので、date1 < date2
はtrue
になります。
ただし、==
や===
での等価比較は少し注意が必要です。
同じ日付でも、異なるオブジェクトなのでfalse
になってしまいます。
正しい等価比較の方法
同じ日付かどうかを正確に判定するには、特別な方法を使います。
// 正しい等価比較の方法let date1 = new Date("2025-01-10");let date2 = new Date("2025-01-10");
// 方法1: getTime()を使用console.log("getTime()で比較:", date1.getTime() === date2.getTime()); // true
// 方法2: valueOf()を使用console.log("valueOf()で比較:", date1.valueOf() === date2.valueOf()); // true
// 方法3: 数値に変換console.log("数値変換で比較:", +date1 === +date2); // true
// 実用的な関数function isSameDate(date1, date2) { return date1.getTime() === date2.getTime();}
console.log("関数で比較:", isSameDate(date1, date2)); // true
getTime()
やvalueOf()
を使うことで、ミリ秒値で比較できます。
これなら同じ日付を正確に判定できますね。
+date1
のように+記号をつけると、自動的に数値(ミリ秒値)に変換されます。
これも便利なテクニックです。
今日の日付との比較
実際のアプリケーションでは、「今日との比較」がよく使われます。
// 今日の日付を取得let today = new Date();let specificDate = new Date("2025-12-25");
// 今日との比較function compareDates(targetDate) { let now = new Date(); if (targetDate > now) { return "未来の日付です"; } else if (targetDate < now) { return "過去の日付です"; } else { return "今日の日付です"; }}
console.log("クリスマス:", compareDates(specificDate));
// より詳細な比較function getDateComparison(targetDate) { let now = new Date(); let diffMs = targetDate.getTime() - now.getTime(); let diffDays = Math.ceil(diffMs / (1000 * 60 * 60 * 24)); if (diffDays > 0) { return `${diffDays}日後です`; } else if (diffDays < 0) { return `${Math.abs(diffDays)}日前です`; } else { return "今日です"; }}
console.log("詳細比較:", getDateComparison(specificDate));
compareDates
関数では、未来・過去・今日の判定をしています。
getDateComparison
関数では、何日前・何日後かまで計算していますね。
Math.ceil()
で切り上げることで、日数を整数にしています。
Math.abs()
で絶対値を取ることで、マイナスをプラスに変換しています。
日付のみの比較(時刻を無視)
時刻部分を削除した比較
「同じ日付かどうか」を調べたいとき、時刻は関係ありませんよね。 そんな場合は、時刻部分をリセットする方法があります。
// 時刻を含む日付let datetime1 = new Date("2025-01-10 14:30:00");let datetime2 = new Date("2025-01-10 18:45:00");
console.log("時刻込み比較:", datetime1.getTime() === datetime2.getTime()); // false
// 日付のみに正規化する関数function getDateOnly(date) { let newDate = new Date(date); newDate.setHours(0, 0, 0, 0); // 時、分、秒、ミリ秒を0にリセット return newDate;}
let dateOnly1 = getDateOnly(datetime1);let dateOnly2 = getDateOnly(datetime2);
console.log("日付のみ比較:", dateOnly1.getTime() === dateOnly2.getTime()); // true
// より簡潔な方法function isSameDay(date1, date2) { return date1.toDateString() === date2.toDateString();}
console.log("toDateString()で比較:", isSameDay(datetime1, datetime2)); // true
setHours(0, 0, 0, 0)
で時刻を午前0時にリセットしています。
これで純粋に日付だけの比較ができますね。
toDateString()
メソッドは、日付部分だけを文字列で返してくれます。
これを比較することで、より簡単に同じ日かどうかが分かります。
年月日の個別比較
年、月、日を個別にチェックする方法も便利です。
// 年月日を個別に比較する関数function compareDateParts(date1, date2) { let year1 = date1.getFullYear(); let month1 = date1.getMonth(); let day1 = date1.getDate(); let year2 = date2.getFullYear(); let month2 = date2.getMonth(); let day2 = date2.getDate(); return { sameYear: year1 === year2, sameMonth: month1 === month2, sameDay: day1 === day2, sameDate: year1 === year2 && month1 === month2 && day1 === day2 };}
let date1 = new Date("2025-01-15 10:30:00");let date2 = new Date("2025-01-15 20:45:00");let comparison = compareDateParts(date1, date2);
console.log("年月日比較:", comparison);// { sameYear: true, sameMonth: true, sameDay: true, sameDate: true }
この関数では、年・月・日それぞれが同じかどうかを詳しくチェックしています。 結果をオブジェクトで返すので、用途に応じて使い分けできますね。
実用的な日付チェック関数も作ってみましょう。
// 実用的な日付チェック関数function isToday(date) { let today = new Date(); return compareDateParts(date, today).sameDate;}
function isYesterday(date) { let yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); return compareDateParts(date, yesterday).sameDate;}
function isTomorrow(date) { let tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); return compareDateParts(date, tomorrow).sameDate;}
// テストlet testDate = new Date();console.log("今日?", isToday(testDate)); // trueconsole.log("昨日?", isYesterday(testDate)); // falseconsole.log("明日?", isTomorrow(testDate)); // false
setDate()
メソッドで日付を変更しています。
getDate() - 1
で昨日、getDate() + 1
で明日の日付を作れます。
期間の判定をマスターしよう
範囲内チェック
特定の期間内にあるかどうかを判定するのは、よくある処理です。
// 期間チェック関数function isDateInRange(targetDate, startDate, endDate) { return targetDate >= startDate && targetDate <= endDate;}
// 営業時間内チェックfunction isBusinessHours(date) { let hours = date.getHours(); return hours >= 9 && hours < 18; // 9時〜18時}
// 営業日チェック(土日を除く)function isBusinessDay(date) { let dayOfWeek = date.getDay(); // 0=日曜, 1=月曜, ..., 6=土曜 return dayOfWeek >= 1 && dayOfWeek <= 5;}
// 年末年始期間チェックfunction isNewYearPeriod(date) { let year = date.getFullYear(); let startDate = new Date(year - 1, 11, 29); // 前年12月29日 let endDate = new Date(year, 0, 3); // 当年1月3日 return isDateInRange(date, startDate, endDate);}
isDateInRange
関数は、開始日と終了日の間にあるかを判定します。
>=
と<=
を使うことで、境界の日付も含めて判定していますね。
getDay()
メソッドで曜日を取得できます。
0が日曜日、1が月曜日、6が土曜日になります。
年末年始の期間チェックでは、前年と当年をまたいだ判定をしています。
実際にテストしてみましょう。
// テストlet testDates = [ new Date("2025-01-01"), // 元旦 new Date("2025-03-15"), // 平日 new Date("2025-12-31") // 大晦日];
testDates.forEach(date => { console.log(`${date.toLocaleDateString("ja-JP")}:`); console.log(` 営業日: ${isBusinessDay(date)}`); console.log(` 年末年始: ${isNewYearPeriod(date)}`);});
toLocaleDateString("ja-JP")
で、日本語形式の日付文字列を取得しています。
forEach
で配列の各要素に対して処理を実行していますね。
期間の長さ計算
日数の差分や詳細な期間計算も重要な機能です。
// 日数差を計算する関数function daysDifference(date1, date2) { let timeDiff = Math.abs(date2.getTime() - date1.getTime()); return Math.ceil(timeDiff / (1000 * 60 * 60 * 24));}
// より詳細な期間計算function getDetailedDifference(startDate, endDate) { let diffMs = endDate.getTime() - startDate.getTime(); let days = Math.floor(diffMs / (1000 * 60 * 60 * 24)); let hours = Math.floor((diffMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); let minutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60)); let seconds = Math.floor((diffMs % (1000 * 60)) / 1000); return { totalMs: diffMs, days: days, hours: hours, minutes: minutes, seconds: seconds, isPositive: diffMs >= 0 };}
Math.abs()
で絶対値を取ることで、常に正の値が得られます。
Math.ceil()
で切り上げ、Math.floor()
で切り捨てを使い分けています。
詳細な期間計算では、余りを使って時分秒まで計算しています。
%
演算子で余りを求めて、段階的に計算していますね。
年齢計算の例も見てみましょう。
// 年齢計算function calculateAge(birthDate, referenceDate = new Date()) { let age = referenceDate.getFullYear() - birthDate.getFullYear(); let monthDiff = referenceDate.getMonth() - birthDate.getMonth(); // 誕生日がまだ来ていない場合は1歳引く if (monthDiff < 0 || (monthDiff === 0 && referenceDate.getDate() < birthDate.getDate())) { age--; } return age;}
// 使用例let startDate = new Date("2025-01-01");let endDate = new Date("2025-01-15");let birthDate = new Date("1990-06-15");
console.log("日数差:", daysDifference(startDate, endDate));console.log("詳細差分:", getDetailedDifference(startDate, endDate));console.log("年齢:", calculateAge(birthDate));
年齢計算では、単純に年の差を取るだけでなく、誕生日が来ているかもチェックしています。 これにより、正確な満年齢を計算できます。
実践的なアプリケーションを作ってみよう
タスク管理システム
期限管理ができるタスク管理システムを作ってみましょう。
// タスク管理システムclass TaskManager { constructor() { this.tasks = []; } // タスクを追加 addTask(title, dueDate, priority = "中") { let task = { id: Date.now(), title: title, dueDate: new Date(dueDate), priority: priority, completed: false, createdAt: new Date() }; this.tasks.push(task); console.log(`タスク「${title}」を追加しました`); } // 期限切れタスクを取得 getOverdueTasks() { let now = new Date(); return this.tasks.filter(task => { return !task.completed && task.dueDate < now; }); } // 今日が期限のタスクを取得 getTodayTasks() { let today = new Date(); return this.tasks.filter(task => { return !task.completed && this.isSameDay(task.dueDate, today); }); } // 今週が期限のタスクを取得 getThisWeekTasks() { let now = new Date(); let weekFromNow = new Date(); weekFromNow.setDate(now.getDate() + 7); return this.tasks.filter(task => { return !task.completed && task.dueDate >= now && task.dueDate <= weekFromNow; }); } // 日付が同じかチェック isSameDay(date1, date2) { return date1.toDateString() === date2.toDateString(); } // タスクの緊急度を計算(期限の近さと重要度) calculateUrgency(task) { let now = new Date(); let diffDays = Math.ceil((task.dueDate - now) / (1000 * 60 * 60 * 24)); let priorityScore = { "高": 3, "中": 2, "低": 1 }[task.priority]; let urgencyScore = Math.max(0, 10 - diffDays); // 期限が近いほど高得点 return priorityScore * urgencyScore; }}
このクラスでは、タスクの追加から期限管理まで一通りの機能を実装しています。
filter
メソッドで条件に合うタスクを絞り込んでいますね。
期限切れのチェックでは、現在時刻との比較を行っています。 今週のタスク検索では、7日後の日付を作って範囲指定しています。
続きの機能も実装してみましょう。
// 緊急度順にタスクを取得 getTasksByUrgency() { return [...this.tasks] .filter(task => !task.completed) .sort((a, b) => this.calculateUrgency(b) - this.calculateUrgency(a)); } // タスク一覧を表示 displayTasks(tasks = this.tasks) { tasks.forEach(task => { let status = task.completed ? "✓" : "○"; let urgency = this.calculateUrgency(task); let daysUntilDue = Math.ceil((task.dueDate - new Date()) / (1000 * 60 * 60 * 24)); console.log( `${status} [${task.priority}] ${task.title} ` + `(期限: ${task.dueDate.toLocaleDateString("ja-JP")}, ` + `残り${daysUntilDue}日, 緊急度: ${urgency})` ); }); }}
// 使用例let taskManager = new TaskManager();
taskManager.addTask("プレゼン準備", "2025-01-08", "高");taskManager.addTask("レポート提出", "2025-01-10", "中");taskManager.addTask("本を読む", "2025-01-20", "低");taskManager.addTask("メール返信", "2025-01-07", "中");
console.log("=== 緊急度順タスク ===");taskManager.displayTasks(taskManager.getTasksByUrgency());
console.log("=== 期限切れタスク ===");taskManager.displayTasks(taskManager.getOverdueTasks());
sort
メソッドで緊急度順にソートしています。
...
スプレッド演算子で配列をコピーしてから操作することで、元の配列を変更せずに済みます。
表示機能では、残り日数や緊急度も一緒に表示しています。
イベントスケジュール管理
次は、イベントの重複チェックができるスケジュール管理システムです。
// イベント管理システムclass EventScheduler { constructor() { this.events = []; } // イベントを追加 addEvent(title, startDate, endDate, location = "") { let event = { id: Date.now(), title: title, startDate: new Date(startDate), endDate: new Date(endDate), location: location, createdAt: new Date() }; this.events.push(event); console.log(`イベント「${title}」を追加しました`); } // 特定日のイベントを取得 getEventsOnDate(targetDate) { return this.events.filter(event => { let targetStart = new Date(targetDate); targetStart.setHours(0, 0, 0, 0); let targetEnd = new Date(targetDate); targetEnd.setHours(23, 59, 59, 999); return (event.startDate <= targetEnd && event.endDate >= targetStart); }); } // 今週のイベントを取得 getThisWeekEvents() { let now = new Date(); let startOfWeek = new Date(now); startOfWeek.setDate(now.getDate() - now.getDay()); // 日曜日から startOfWeek.setHours(0, 0, 0, 0); let endOfWeek = new Date(startOfWeek); endOfWeek.setDate(startOfWeek.getDate() + 6); endOfWeek.setHours(23, 59, 59, 999); return this.events.filter(event => { return (event.startDate <= endOfWeek && event.endDate >= startOfWeek); }); } // 期間が重複するイベントをチェック findConflictingEvents(startDate, endDate) { let newStart = new Date(startDate); let newEnd = new Date(endDate); return this.events.filter(event => { return (newStart < event.endDate && newEnd > event.startDate); }); } // 次のイベントを取得 getNextEvent() { let now = new Date(); let futureEvents = this.events.filter(event => event.startDate > now); if (futureEvents.length === 0) return null; return futureEvents.reduce((nearest, current) => { return current.startDate < nearest.startDate ? current : nearest; }); }}
このシステムでは、日付の範囲を使った様々な機能を実装しています。
特定日のイベント取得では、その日の0時から23:59:59までの範囲でチェックしています。 今週のイベント取得では、日曜日から土曜日までの1週間で絞り込んでいます。
重複チェックでは、期間の重なりを判定しています。 新しいイベントの開始時刻が既存イベントの終了時刻より前で、新しいイベントの終了時刻が既存イベントの開始時刻より後なら重複です。
続きの機能も見てみましょう。
// イベント表示 displayEvents(events = this.events) { events.sort((a, b) => a.startDate - b.startDate); events.forEach(event => { let startStr = event.startDate.toLocaleString("ja-JP"); let endStr = event.endDate.toLocaleString("ja-JP"); let location = event.location ? ` at ${event.location}` : ""; console.log(`${event.title}${location}`); console.log(` ${startStr} 〜 ${endStr}`); }); }}
// 使用例let scheduler = new EventScheduler();
scheduler.addEvent("チーム会議", "2025-01-10 10:00", "2025-01-10 11:00", "会議室A");scheduler.addEvent("プロジェクト発表", "2025-01-12 14:00", "2025-01-12 15:30", "講堂");scheduler.addEvent("研修", "2025-01-15 09:00", "2025-01-15 17:00", "研修室");
console.log("=== 今週のイベント ===");scheduler.displayEvents(scheduler.getThisWeekEvents());
console.log("=== 次のイベント ===");let nextEvent = scheduler.getNextEvent();if (nextEvent) { scheduler.displayEvents([nextEvent]);}
// 重複チェックconsole.log("=== 重複チェック ===");let conflicts = scheduler.findConflictingEvents("2025-01-10 10:30", "2025-01-10 11:30");if (conflicts.length > 0) { console.log("重複するイベントが見つかりました:"); scheduler.displayEvents(conflicts);}
表示機能では、開始時刻順にソートしてから表示しています。
toLocaleString("ja-JP")
で日本語形式の日時文字列を取得していますね。
重複チェックの結果も、分かりやすく表示されます。
よくある間違いと対策方法
タイムゾーンの問題
日付を扱う際に最も注意が必要なのが、タイムゾーンの問題です。
// 問題のある例:タイムゾーンの考慮不足let utcDate = new Date("2025-01-01T12:00:00Z"); // UTC時刻let localDate = new Date("2025-01-01T12:00:00"); // ローカル時刻
console.log("UTC日付:", utcDate.toString());console.log("ローカル日付:", localDate.toString());console.log("同じ?", utcDate.getTime() === localDate.getTime()); // false(時差分異なる)
// 解決方法:統一したタイムゾーンで比較function compareUTCDates(date1, date2) { return date1.getTime() === date2.getTime();}
function compareLocalDates(date1, date2) { // ローカル時刻として正規化 let local1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()); let local2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()); return local1.getTime() === local2.getTime();}
文字列の最後に「Z」がついているとUTC時刻として解釈されます。 ついていないとローカル時刻として解釈されるので、時差の分だけ異なる値になってしまいます。
どちらかのタイムゾーンに統一して比較することが重要です。
月の指定ミス
JavaScriptの月は0から始まるので、間違いやすいポイントです。
// 問題のある例:月は0から始まるlet wrongDate = new Date(2025, 1, 15); // 実際は2025年2月15日let correctDate = new Date(2025, 0, 15); // 2025年1月15日
console.log("間違った指定:", wrongDate.toLocaleDateString("ja-JP"));console.log("正しい指定:", correctDate.toLocaleDateString("ja-JP"));
// 安全な日付作成関数function createSafeDate(year, month, day) { // 月を1から12で指定可能にする return new Date(year, month - 1, day);}
let safeDate = createSafeDate(2025, 1, 15); // 2025年1月15日console.log("安全な作成:", safeDate.toLocaleDateString("ja-JP"));
createSafeDate
関数では、月を普通の感覚(1〜12)で指定できるようにしています。
関数内で1を引くことで、JavaScriptの0ベースに調整していますね。
文字列パースの問題
日付の文字列をパースする際も注意が必要です。
// 問題のある例:曖昧な文字列パースlet ambiguousDate1 = new Date("01/02/2025"); // MM/DD/YYYY? DD/MM/YYYY?let ambiguousDate2 = new Date("2025/01/02"); // より明確
console.log("曖昧な指定:", ambiguousDate1.toLocaleDateString("ja-JP"));console.log("明確な指定:", ambiguousDate2.toLocaleDateString("ja-JP"));
// 安全な文字列パースfunction parseISODate(dateString) { // ISO 8601形式(YYYY-MM-DD)を前提 let parts = dateString.split('-'); if (parts.length === 3) { let year = parseInt(parts[0]); let month = parseInt(parts[1]) - 1; // 0ベースに調整 let day = parseInt(parts[2]); return new Date(year, month, day); } throw new Error("不正な日付形式です");}
try { let parsedDate = parseISODate("2025-01-15"); console.log("パース成功:", parsedDate.toLocaleDateString("ja-JP"));} catch (error) { console.error("パースエラー:", error.message);}
「01/02/2025」のような形式は、MM/DD/YYYYかDD/MM/YYYYか曖昧です。 「YYYY-MM-DD」のようなISO 8601形式を使うことで、誤解を防げます。
parseISODate
関数では、フォーマットをチェックしてから安全にパースしています。
まとめ
JavaScriptのDateオブジェクトを使った日付比較について、基本から応用まで詳しく学習しました。
今回マスターした内容:
- 基本的な比較方法:比較演算子とgetTime()の使い分け
- 日付のみの比較:時刻を無視した判定方法
- 期間の判定:範囲チェックと期間計算
- 実践的な応用:タスク管理とスケジュール管理システム
重要なポイント:
- Dateオブジェクトは内部的にミリ秒で管理されている
- 等価比較にはgetTime()を使う
- 月の指定は0から始まることに注意
- タイムゾーンの違いに気をつける
実用的なテクニック:
- 時刻をリセットした日付のみ比較
- 期間の重複判定
- 緊急度の計算
- 年齢や日数差の正確な計算
Dateオブジェクトを使った日付比較は、Webアプリケーション開発で必須のスキルです。 期限管理、スケジュール管理、データの絞り込みなど、様々な場面で活用できます。
今回学んだ知識を活用して、ぜひ実用的な日付管理機能を開発してみてください。 最初は簡単な期限チェックから始めて、徐々に複雑な機能に挑戦していけば、必ずスキルアップできますよ!