C# Tips | 日付・時間処理:日付比較

C# C#
スポンサーリンク

はじめに 「日付比較」は“ビジネスルールをコードに落とす入り口”

「締切を過ぎているか?」「この期間内か?」「開始日より前か後か?」
業務システムで“条件分岐”を書くとき、ほぼ必ず出てくるのが「日付比較」です。

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 には、CompareCompareTo という比較用メソッドもあります。

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# コードの中に自信を持って組み込めるようになります。

タイトルとURLをコピーしました