はじめに 「日付比較」は“ビジネスルールをコードに落とす入り口”
「締切を過ぎているか?」「この期間内か?」「開始日より前か後か?」
業務システムで“条件分岐”を書くとき、ほぼ必ず出てくるのが「日付比較」です。
C# では DateTime 同士をそのまま比較できますが、
「日付だけを比べたいのか」「時刻も含めて比べたいのか」「境界を含むのか」
を意識しないと、微妙なバグを生みやすいところでもあります。
ここでは、
基本の比較演算子から、「日付だけの比較」「期間内判定」「締切判定ユーティリティ」、
そして DateTimeKind やタイムゾーンの落とし穴まで、
初心者向けにかみ砕いて解説していきます。
基本:DateTime 同士は比較演算子でそのまま比べられる
大なり・小なり・等しいの基本形
DateTime は、< <= > >= == != でそのまま比較できます。
比較されるのは「日時の早い・遅い」です。
using System;
DateTime a = new DateTime(2026, 2, 10, 9, 0, 0);
DateTime b = new DateTime(2026, 2, 10, 18, 0, 0);
Console.WriteLine(a < b); // true
Console.WriteLine(a > b); // false
Console.WriteLine(a == b); // false
C#ここで比べているのは「2026/02/10 09:00:00」と「2026/02/10 18:00:00」という“日時”です。
つまり、日付だけでなく時刻まで含めて比較している、ということを意識してください。
「締切日時を過ぎているか?」のような判定は、
この比較演算子で素直に書けます。
DateTime deadline = new DateTime(2026, 2, 10, 23, 59, 59);
DateTime now = DateTime.Now;
bool isOver = now > deadline;
C#日付だけを比較したいときは .Date を使う
時刻を無視して「日付同士」を比べる
業務では、「2026/02/10 かどうか」「今日かどうか」のように、
時刻は無視して“日付だけ”を比べたいことがよくあります。
その場合は、DateTime.Date プロパティを使います。
これは「その日の 0:00:00 にそろえた DateTime」を返します。
DateTime x = new DateTime(2026, 2, 10, 9, 30, 0);
DateTime y = new DateTime(2026, 2, 10, 18, 0, 0);
Console.WriteLine(x == y); // false(時刻が違う)
Console.WriteLine(x.Date == y.Date); // true(日付だけなら同じ)
C#「今日かどうか」を判定するユーティリティは、こう書けます。
public static bool IsToday(DateTime target)
{
return target.Date == DateTime.Today;
}
C#ここでの重要ポイントは、
「日付だけを比べたいときは、必ず .Date を通してから比較する」
という習慣をつけることです。
これを忘れると、「同じ日なのに違うと判定される」バグが生まれます。
期間内判定:「from〜to の間に含まれるか?」
境界を含むかどうかをはっきり決める
「この日付が、開始日と終了日の間に入っているか?」
という判定も、業務で頻出です。
例えば、「2026/02/10〜2026/02/20 の期間内か?」を判定する場合、
よく使うパターンは「両端を含む」か「終了日を含まない」かのどちらかです。
両端を含む(閉区間)の例です。
public static bool IsBetweenInclusive(DateTime target, DateTime from, DateTime to)
{
return from <= target && target <= to;
}
C#終了日を含まない(半開区間)の例です。
public static bool IsBetweenHalfOpen(DateTime target, DateTime from, DateTime to)
{
return from <= target && target < to;
}
C#どちらが正しいかは要件次第ですが、
「どちらのルールか」をメソッド名やコメントで明示することがとても大事です。
日付だけで判定したい場合は、引数に .Date をかけてから比較します。
public static bool IsBetweenDateInclusive(DateTime target, DateTime from, DateTime to)
{
DateTime d = target.Date;
DateTime f = from.Date;
DateTime t = to.Date;
return f <= d && d <= t;
}
C#締切判定ユーティリティ:「期限内か」「期限切れか」
「締切を過ぎているか?」を分かりやすく書く
締切判定は、日付比較の典型例です。
例えば、「締切日を含めて有効」「締切日を過ぎたら無効」という仕様なら、
次のように書けます。
public static bool IsBeforeOrOnDeadline(DateTime now, DateTime deadline)
{
return now <= deadline;
}
public static bool IsExpired(DateTime now, DateTime deadline)
{
return now > deadline;
}
C#日付だけで締切を扱う場合(時刻は関係ない場合)は、.Date を使って日付にそろえます。
public static bool IsBeforeOrOnDeadlineDate(DateTime now, DateTime deadlineDate)
{
return now.Date <= deadlineDate.Date;
}
C#ここでのポイントは、
「有効かどうか」「期限切れか」を
メソッド名でそのまま表現してしまうことです。now > deadline のような生の比較をあちこちに書くより、
読みやすさとバグの防止につながります。
DateTime.Compare と CompareTo の使いどころ
結果を -1 / 0 / 1 で受け取りたいとき
DateTime には、Compare と CompareTo という比較用メソッドもあります。
DateTime a = new DateTime(2026, 2, 10);
DateTime b = new DateTime(2026, 2, 11);
int r1 = DateTime.Compare(a, b); // a < b → 負の値
int r2 = a.CompareTo(b); // 同じ意味
Console.WriteLine(r1); // 例: -1
Console.WriteLine(r2); // 例: -1
C#戻り値の意味は、
負 → 左が右より前
0 → 同じ
正 → 左が右より後
です。
ソートや、
「前・同じ・後」の3パターンを switch で分けたいときなどに使えます。
ただし、単純な条件分岐なら、< > == を使ったほうが読みやすいことが多いです。
実務での落とし穴1:DateTimeKind とタイムゾーン
「同じ瞬間なのに違うと判定される」問題
DateTime には Kind(Utc / Local / Unspecified)があり、
内部的な扱いが変わります。
例えば、次の2つは「日本時間で同じ瞬間」ですが、== で比べると false になります。
DateTime utc = new DateTime(2026, 2, 10, 0, 0, 0, DateTimeKind.Utc);
DateTime jst = new DateTime(2026, 2, 10, 9, 0, 0, DateTimeKind.Local);
Console.WriteLine(utc == jst); // false
C#DateTime の比較は「そのままの値同士」を比べるだけで、
「これはUTCだから9時間足して…」などの補正はしてくれません。
「同じ瞬間かどうか」を比べたいなら、
両方を UTC にそろえてから比較する必要があります。
DateTime utc1 = utc.ToUniversalTime();
DateTime utc2 = jst.ToUniversalTime();
Console.WriteLine(utc1 == utc2); // true
C#実務では、
保存・比較は UTC で行う
画面表示だけローカル時間に変換する
という方針にしておくと、
「同じ瞬間なのに違うと判定される」問題を避けやすくなります。
実務での落とし穴2:日付と日時を混ぜて比較する
「2026/02/10 00:00:00」と「2026/02/10 23:59:59」は違う
よくあるバグとして、
「締切日を 2026/02/10 00:00:00 として保存してしまい、
当日の 10:00 に比較すると“もう過ぎている”と判定される」
というものがあります。
例えば、こういうコードです。
DateTime deadline = new DateTime(2026, 2, 10); // 2026/02/10 00:00:00
DateTime now = new DateTime(2026, 2, 10, 10, 0, 0);
bool expired = now > deadline; // true(当日なのに期限切れ扱い)
C#「日付としての締切」を扱いたいなら、
「締切日の終わり」か「日付だけの比較」にする必要があります。
日付だけで比較する例です。
bool expired = now.Date > deadline.Date;
C#あるいは、「締切日の 23:59:59.999 まで有効」として扱う方法もありますが、
ミリ秒まで意識する必要が出てくるので、
多くの場合は「日付だけで比較する」ほうがシンプルです。
まとめ 「日付比較ユーティリティ」は“ビジネスの境界線をコードに刻むもの」
日付比較は、一見シンプルですが、
「日付だけか、時刻も含めるか」「境界を含むか」「どのタイムゾーンか」
といった要素が絡む、実は奥の深いテーマです。
押さえておきたいポイントを整理すると、こうなります。
DateTime 同士は比較演算子でそのまま比べられるが、それは“日時(時刻込み)”の比較である。
日付だけを比べたいときは、必ず .Date を使ってから比較することで、「同じ日なのに違う」といったバグを防げる。
期間内判定や締切判定では、「境界を含むかどうか」を仕様として決め、メソッド名やユーティリティで明示する。DateTimeKind やタイムゾーンを意識し、「同じ瞬間かどうか」を比べたいときは UTC にそろえてから比較する。
「日付としての締切」を扱うときは、時刻を 0:00:00 のまま比較しないで、日付比較か“終わりの時刻”をどうするかを設計する。
ここを押さえておけば、
「なんとなく > や == を書いている」状態から一歩進んで、
“ビジネスルールの境界線を正しく表現できる、実務で使える日付比較ユーティリティ”を
自分の C# コードの中に自信を持って組み込めるようになります。
