【初心者救済】JavaScript日付比較がわからない?シンプルな解決法教えます
こんにちは、とまだです。
「JavaScriptで日付比較をしたいけど、Dateオブジェクトがよくわからない...」って悩んでいませんか?
実は私も最初は日付の扱いでめちゃくちゃ苦労しました。「getTime()ってなに?」「なんで同じ日付なのに===で比較できないの?」って感じで、本当に意味不明でした。
でも安心してください。今回は、プログラミングスクールで教えていた経験をもとに、誰でも理解できる日付比較の方法をお教えします。
実務でよくある期限チェックやイベント管理など、実践的な例もたくさん紹介しますので、きっと役に立つと思いますよ。
この記事を読むとわかること
- JavaScriptで日付オブジェクトを生成する基本的な方法
- 日付を比較するときの考え方と、よく使われるメソッドの使い方
- 実務で役立つ日付比較の具体例(期限切れチェックや期間判定など)
- サードパーティのライブラリを使った日付比較のやり方と注意点
- タイムゾーンやUTCを含むエッジケースへの対応方法
JavaScriptの日付を扱う基礎知識
JavaScriptで日付を操作する際は、Dateオブジェクトが中心的な役割を果たします。
ただし、Date
は一見シンプルに見える反面、内部的にはUTCをベースにしていたり、メソッドごとに返す値が異なったりと混乱しやすい点がいくつかあります。
まずは基礎知識として、Dateオブジェクトの生成方法とフォーマットのポイントを簡単におさえましょう。
Dateオブジェクトの基本
Dateオブジェクトは、以下のようにコンストラクタを使って生成します。 何も引数を与えなければ、システムの現在時刻が反映されたDateオブジェクトが作られます。
// 現在の日時を取得
const now = new Date();
console.log(now);
たとえば、特定の日付や時刻を扱いたい場合は、引数で年月日や時刻情報を渡します。 文字列として日付を指定することも可能です。
// "YYYY-MM-DD" 形式で文字列を渡す
const specificDate = new Date("2025-12-31");
console.log(specificDate);
// 年月日など数値を個別に渡す(注意:月は0始まり)
const anotherDate = new Date(2025, 11, 31, 23, 59);
console.log(anotherDate);
なお、数値で月を指定する場合は0が1月、11が12月を表すため、その点だけは慣れるまで注意が必要です。
文字列から日付を生成する
日付の文字列パースでは、ブラウザや環境によって解釈が異なるケースもあります。 なるべく「YYYY-MM-DD」形式など、一般的に認識しやすいフォーマットを使用するようにすると、思わぬトラブルを防ぎやすいです。 日付比較の際はまず正しくDateオブジェクトを生成できているかどうかを確認しましょう。
日付のフォーマット
JavaScriptの標準APIで日付を文字列に整形したい場合、toLocaleDateString()
や toLocaleString()
などのメソッドを使います。
このとき、各国の言語やタイムゾーンを指定するオプションを与えることもできます。
const date = new Date("2025-12-31");
console.log(date.toLocaleDateString("ja-JP"));
フォーマットを細かく制御したい場合は、標準APIだけでは柔軟性が足りないと感じることがあるかもしれません。 その場合はライブラリに頼るのも選択肢ですが、まずは標準のメソッドでも基本的な操作は可能という点を理解しておきましょう。
タイムゾーンとUTC
JavaScriptのDateオブジェクトは、内部ではUTC(協定世界時)を基準としつつ、メソッドによってはローカルタイムを返すという特徴があります。
getTime()
で取得できるのは「1970年1月1日 0時0分0秒 UTCからの経過ミリ秒数」であり、これを活用して日付比較を行うケースも多いです。
一方、getFullYear()
や getMonth()
はローカルタイムをもとに計算された値を返します。
そのため、タイムゾーンが異なるユーザーが利用するシステムを作る場合には注意が必要です。
日付比較の基本概念
整数や文字列の比較なら ===
や >
、<
を使うだけですが、日付オブジェクトの場合は少し工夫が必要になります。
理由としては、オブジェクト同士を直接 ===
で比較しても、「同じインスタンスかどうか」という判定しか行われないためです。
つまり、同じ日時でも別々に生成したDateオブジェクトならば異なるものとみなされてしまいます。
オブジェクト同士の比較が難しい理由
たとえば、次のようなコードを見てみましょう。
const dateA = new Date("2025-12-31");
const dateB = new Date("2025-12-31");
console.log(dateA === dateB); // false
両者は同じタイムスタンプ(同じ時間)を指しているように見えますが、別々に作られたインスタンスなので false
になります。
これはオブジェクト型の基本的な性質であり、「値」の等価ではなく「参照」が同じであるかをチェックしているためです。
getTime() メソッドを使う
では、同じ日時かどうかを正しく判定するにはどうすればいいのでしょうか。
ここで役立つのが getTime()
メソッドです。
これはDateオブジェクトが持つ「UTCエポックからの経過ミリ秒数」を数値として返すため、単純な数値比較で判定できます。
const dateA = new Date("2025-12-31");
const dateB = new Date("2025-12-31");
console.log(dateA.getTime() === dateB.getTime()); // true
getTime() を使えば、日時の早い・遅いや、同じ瞬間かどうかを簡単に比較できるわけです。 この方法を応用して、後述の「範囲内に含まれるかどうか」「何日後か」といった処理を実装することも多々あります。
実務で使う日付比較のパターン
実際の開発現場では、単に「同じ日かどうか」だけでなく、いろいろな比較が求められます。 ここからは代表的なパターンをいくつか取り上げ、コード例を交えながら見ていきましょう。
同一かどうか判定する
「同じ日付」かを判定する最も基本的な方法は、先述したとおり getTime()
を使った等値比較です。
ただし、ここで注意したいのは「日付だけが同じか」「時刻まで含めて同じか」の違いです。
時分秒の情報まで含めて一致させたい場合は、getTime()
の比較で十分ですが、「日付(年月日)レベルで一致するか」を見たいときは、もう少し工夫が必要になります。
function isSameDate(d1, d2) {
return (
d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate()
);
}
const dateA = new Date("2025-12-31T10:00:00");
const dateB = new Date("2025-12-31T23:59:59");
console.log(isSameDate(dateA, dateB)); // true
上記のように、年・月・日をそれぞれ比較すると、時間帯が異なっていても同じ「日付」として扱えます。
日付が過去か未来かを判定する
特定の日付が「今日より前なのか、後なのか」を判定する状況は多々あります。
たとえば、有効期限が切れているかどうかをチェックしたい場合などは、以下のように getTime()
を用いて比較を行います。
function isPast(date) {
const now = new Date();
return date.getTime() < now.getTime();
}
function isFuture(date) {
const now = new Date();
return date.getTime() > now.getTime();
}
const deadline = new Date("2025-01-01");
console.log(isPast(deadline)); // 期限を過ぎているかどうか
console.log(isFuture(deadline)); // 将来の日付かどうか
用途に応じて、現時点との比較だけでなく、特定の基準日時を別途設定して比較することも考えられます。
日数の差を求める
たとえば「イベントまであと何日あるのか」「契約更新日がどれくらい先なのか」といった計算をしたいケースがあります。
日数の差を調べるには、2つのDateオブジェクトの getTime()
の差分を求め、ミリ秒から日数に換算する方法がよく用いられます。
function diffInDays(dateA, dateB) {
const msPerDay = 24 * 60 * 60 * 1000;
// 絶対値をとることで、どちらが先でも正の値を返す
return Math.floor(Math.abs(dateA.getTime() - dateB.getTime()) / msPerDay);
}
const eventDate = new Date("2025-12-31");
const today = new Date();
console.log(diffInDays(eventDate, today) + "日差があります");
これにより、シンプルに日数の差を計算できるため、日付関連のメッセージ表示などに応用しやすいです。
期間内に含まれるかどうか判定する
たとえば「指定した期間内にイベントを行うか」「キャンペーンの対象期間にあるか」など、範囲判定が必要な状況もよくあります。
下記の例では、startDate
と endDate
の間に targetDate
があるかを確認します。
function isWithinRange(targetDate, startDate, endDate) {
const targetTime = targetDate.getTime();
return (
targetTime >= startDate.getTime() &&
targetTime <= endDate.getTime()
);
}
const start = new Date("2025-01-01");
const end = new Date("2025-01-31");
const check = new Date("2025-01-15");
console.log(isWithinRange(check, start, end)); // true
範囲の下限と上限をどのように含むか(前後を含むのか、含まないのか)によって比較演算子を変えると、さまざまな条件を実現できます。
ライブラリを活用した日付比較
JavaScript標準のDateオブジェクトだけでも十分に比較はできますが、実務ではMoment.jsやdayjs、date-fnsといったライブラリを使うことも多いです。 これらは日付の解析やフォーマット、タイムゾーン調整などを簡潔に書けるため、開発の効率向上につながりやすいメリットがあります。
Moment.jsでの比較
Moment.jsを使うと、moment()
で生成したオブジェクト同士を isSame()
や isBefore()
、isAfter()
などのメソッドで手軽に比較できます。
また、フォーマットやパース機能も充実しているため、開発を進めるうえで強い味方になるでしょう。
// 例:同日かどうかを判定する
const mA = moment("2025-12-31");
const mB = moment("2025-12-31T23:59:59");
console.log(mA.isSame(mB, "day")); // true
ただし、Moment.jsは機能が豊富でサイズが大きいという点から、近年はより軽量なライブラリが人気を集めています。
dayjsでの比較
dayjs はMoment.jsの代替としてよく使われる軽量なライブラリです。
APIの書き方がMoment.jsと似ているため、使い方を移行しやすいメリットがあります。
日付比較にも isSame
や isBefore
、isAfter
といったメソッドが備わっています。
const dA = dayjs("2025-01-01");
const dB = dayjs("2025-02-15");
console.log(dA.isBefore(dB)); // true
date-fnsでの比較
date-fns は純粋関数ベースで日付操作を提供するライブラリです。
compareAsc()
や differenceInDays()
, isWithinInterval()
などの関数を組み合わせて書くスタイルが特徴的で、ツリーシェイキング(使用する機能だけを取り込む)との相性が良い点が魅力です。
import { compareAsc, isWithinInterval } from "date-fns";
const dateC = new Date("2025-01-01");
const dateD = new Date("2025-01-02");
// compareAsc は -1, 0, 1 の数値で早い/同じ/遅いを返す
console.log(compareAsc(dateC, dateD)); // -1
console.log(
isWithinInterval(dateC, {
start: new Date("2024-12-31"),
end: new Date("2025-01-10"),
})
); // true
どのライブラリを使うにしても、それぞれメリットや特徴があり、開発チームやプロジェクト方針によって選定は変わります。 標準のDateオブジェクトで対応できるなら、まずは余計な依存を増やさないのも一つの選択肢かもしれません。
実務での活用シーン
実際のプロジェクトでは、日付比較はどのように応用されるのでしょうか。 ここではいくつか代表的なケースを取り上げてみます。
予約システムでの利用
ホテルやレストランなどの予約システムでは、利用者が選択した日付と既存の予約日との重複をチェックする必要があります。 このとき、範囲比較を行って予約がバッティングしないかどうかを確認するロジックがよく使われます。 また、日付が正しい範囲に入っているか(たとえば「過去の日付は予約不可」など)をチェックするためにも、日付比較の知識が必要になります。
サブスクリプション期間の管理
ユーザーが月額や年額で契約しているサービスでは、契約開始日や終了日を基準に機能の利用可否を判断することが多いです。 こうしたロジックでは、「期限切れを通知する」「期間内だけ特定の機能を有効にする」など、複数の比較パターンが考えられます。 サーバー側でもフロントエンド側でも、しっかりと日付を比較して整合性を取らなければ、ユーザー体験に影響が出てしまいます。
期限切れチェック
ポイントやクーポンなど、有効期限のある機能を提供する場合、「現在時刻が期限を超えていないか」を確認する処理は欠かせません。
多くの場合、getTime()
でミリ秒値を比較するシンプルな形で書かれますが、運用規模が大きくなるとタイムゾーンの扱いに注意が必要です。
サーバーとの通信時差や、ユーザーのローカルタイムとの相違にどこまで対応するか、事前に仕様を固めておくことをおすすめします。
エッジケースや注意点
日付比較は奥が深い分、油断するとバグにつながりやすいという特徴があります。 ここでは初心者が特に引っかかりやすいポイントをいくつか紹介します。
時間帯のズレによる誤差
開発環境と本番環境の時差が異なる場合、ローカルタイムを使った計算では意図しない結果になることがあります。 また、ユーザーが海外にいる場合は、クライアントのタイムゾーンとサーバー側のタイムゾーンが違うケースも多いでしょう。 こうした問題を避けるには、可能な限りUTCで管理し、ユーザーに表示するときだけローカルタイムに変換するという方法が一つの解決策になります。
警告: タイムゾーンが絡む処理では、計算時と表示時で扱いを分けることが重要です。 内部的にはUTCで保管して、UI表示のタイミングでローカルに変換すると、バグが減る傾向があります。
ライブラリ選定のポイント
日付操作ライブラリは複数存在するため、機能面・パフォーマンス面・ファイルサイズなど様々な観点で比較すると良いでしょう。 また、プロジェクトの中で既に特定のライブラリを使用しているのであれば、重複して別のライブラリを導入しないよう注意が必要です。 「標準のDateオブジェクトで十分なときは、それだけで済ませる」というのも1つの立派な選択肢になります。
UTCかローカルか
JavaScriptのDate
メソッドの中には、getUTCFullYear()
や getUTCDate()
のようにUTC基準の値を返すものもあります。
一方で、getFullYear()
や getDate()
はローカルタイム基準なので、同じDateインスタンスから取得する場合でも値が異なる可能性があるのです。
意図せず混在しないように、どの基準で操作するかをチームやプロジェクトで取り決めておきましょう。
注意: 日付の扱いを標準APIだけで完結させるか、専用ライブラリを導入するかはプロジェクトやチームによって異なります。 重要なのは、関わるメンバー全員が「どの基準で日付を扱うか」を明確に把握しておくことです。
まとめ:日付比較をマスターして実務で活躍しよう!
お疲れさまでした!
いかがでしたか?最初は難しそうに見えた日付比較が、意外とシンプルだったことに気づいてもらえたと思います。
今日のおさらいポイント:
- getTime()でミリ秒値比較が基本(これだけで大体OK)
- 日付だけ比較ならgetFullYear()等を使う(時刻を無視したい時)
- タイムゾーンに注意(UTCで管理、表示時にローカル変換)
- ライブラリも便利(moment.js、dayjs、date-fnsなど)
これらのスキルを身につけると、期限チェック、イベント管理、サブスクリプション管理など、実務でめちゃくちゃ使える機能がどんどん作れるようになります。
特に「Dateオブジェクト同士を===で比較しても意味ない」というポイントは、初心者がつまずきやすいところなので、覚えておいてくださいね。
日付比較ができるようになると、Webアプリのレベルが一気に上がります。この調子で、どんどん新しい機能に挑戦していきましょう!
著者について

とまだ
フルスタックエンジニア
Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。
著者の詳細を見る →