C# Tips | 日付・時間処理:日付バリデーション

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

日付バリデーションは“入力のゆらぎを正しい日付に整えるための基盤”

日付入力は業務システムで最もトラブルが起きやすい領域です。
「2026/02/30」「2026-13-01」「20260218」「2/18」など、ユーザーが入力する形式は本当にバラバラです。
さらに、業務では「開始日 ≤ 終了日」「未来日は不可」「過去日は不可」など、追加のルールも絡みます。

ここでは、初心者でも理解しやすいように、

  • 文字列としての形式チェック
  • 実在する日付かどうかのチェック
  • 業務ルール(範囲・前後関係)のチェック

という3段階で、実務で使える日付バリデーションを解説します。


文字列として正しい形式かどうかをチェックする

「YYYY-MM-DD」や「YYYY/MM/DD」を厳密にチェックする

日付は DateTime.Parse に頼るとカルチャ依存で事故が起きるため、
業務では TryParseExact を使って「許可する形式を明示」するのが鉄則です。

using System;
using System.Globalization;

public static class DateValidator
{
    private static readonly string[] Formats =
    {
        "yyyy-MM-dd",
        "yyyy/MM/dd"
    };

    public static bool TryParseDate(string input, out DateTime date)
    {
        return DateTime.TryParseExact(
            input,
            Formats,
            CultureInfo.InvariantCulture,
            DateTimeStyles.None,
            out date);
    }
}
C#

例:正しい形式と誤った形式

DateValidator.TryParseDate("2026-02-18", out var d1); // OK
DateValidator.TryParseDate("2026/02/18", out var d2); // OK
DateValidator.TryParseDate("2026/2/18", out _);       // NG(ゼロ埋め必須)
DateValidator.TryParseDate("2026-13-01", out _);      // NG(存在しない月)
DateValidator.TryParseDate("2026-02-30", out _);      // NG(存在しない日)
C#

ここでの重要ポイントは、
「形式」と「実在する日付かどうか」を同時にチェックできる
という点です。


実在する日付かどうかをチェックする

TryParseExact が通れば「存在する日付」であることが保証される

TryParseExact は、
「2026-02-30」や「2026-13-01」のような存在しない日付を自動的に弾いてくれます。

つまり、

  • 形式が正しい
  • 実在する日付である

この2つを一度に満たすことができます。

ただし、業務ではさらに「意味的に正しいか」をチェックする必要があります。


業務ルール:日付の前後関係をチェックする

「開始日 ≤ 終了日」を保証する

予約・勤怠・期間指定などでは、
開始日と終了日の前後関係が正しいかどうかが必須です。

public static bool IsValidDateRange(DateTime start, DateTime end, bool allowEqual = true)
{
    return allowEqual ? start <= end : start < end;
}
C#

例:前後関係のチェック

DateTime start = new DateTime(2026, 2, 18);
DateTime end   = new DateTime(2026, 2, 20);

IsValidDateRange(start, end); // true
IsValidDateRange(end, start); // false
C#

ここでの重要ポイントは、
「等しい日付を許すかどうか」を引数で切り替えられるようにする
ことです。


業務ルール:許可範囲(未来日禁止・過去日禁止など)

「今日より未来は不可」「過去日は不可」などのチェック

業務によっては、次のような制約があります。

  • 過去日は入力不可(例:予約)
  • 未来日は入力不可(例:実績登録)
  • 今日を含むかどうか

これもユーティリティ化できます。

public static bool IsNotFuture(DateTime date)
{
    return date <= DateTime.Today;
}

public static bool IsNotPast(DateTime date)
{
    return date >= DateTime.Today;
}
C#

例:未来日・過去日の判定

IsNotFuture(new DateTime(2026, 2, 18)); // 今日以前なら OK
IsNotPast(new DateTime(2026, 2, 19));   // 今日以降なら OK
C#

文字列入力から一気に業務ルールまでチェックする

総合的なバリデーション結果を返すクラス

実務では、
「どこがダメだったのか」を画面に返す必要があります。

そのため、結果をオブジェクトで返す形が便利です。

public sealed class DateValidationResult
{
    public bool IsValid { get; }
    public string? ErrorMessage { get; }
    public DateTime? Date { get; }

    private DateValidationResult(bool isValid, string? errorMessage, DateTime? date)
    {
        IsValid = isValid;
        ErrorMessage = errorMessage;
        Date = date;
    }

    public static DateValidationResult Success(DateTime date)
        => new DateValidationResult(true, null, date);

    public static DateValidationResult Fail(string message)
        => new DateValidationResult(false, message, null);
}
C#

総合チェックメソッド

public static class DateInputValidator
{
    public static DateValidationResult Validate(
        string input,
        DateTime? min = null,
        DateTime? max = null)
    {
        if (!DateValidator.TryParseDate(input, out var date))
        {
            return DateValidationResult.Fail("日付の形式が正しくありません。(例: 2026-02-18)");
        }

        if (min.HasValue && date < min.Value)
        {
            return DateValidationResult.Fail($"日付は {min.Value:yyyy-MM-dd} 以降である必要があります。");
        }

        if (max.HasValue && date > max.Value)
        {
            return DateValidationResult.Fail($"日付は {max.Value:yyyy-MM-dd} 以前である必要があります。");
        }

        return DateValidationResult.Success(date);
    }
}
C#

例:入力チェック

var result = DateInputValidator.Validate(
    "2026-02-18",
    min: new DateTime(2026, 1, 1),
    max: new DateTime(2026, 12, 31));

if (!result.IsValid)
{
    Console.WriteLine(result.ErrorMessage);
}
else
{
    Console.WriteLine($"OK: {result.Date}");
}
C#

実務で意識すべきポイント

書式を固定することが最重要

日付はカルチャ依存が強く、
2026/02/18 を「MM/DD/YYYY」と解釈する環境もあります。

業務では必ず、

  • TryParseExact を使う
  • 許可する書式を明示する
  • カルチャは InvariantCulture に固定する

という方針にしておくと事故を防げます。

バリデーションは「入力直後」と「保存直前」の2段階で行う

画面側でチェックしても、
API や DB に渡る前にもう一度チェックするのが安全です。


まとめ:日付バリデーションは“入力の揺れを吸収する安全装置”

日付バリデーションの本質は、

  • 文字列として正しいか
  • 実在する日付か
  • 業務ルールに合っているか

という3段階のチェックを行い、
「システムが安心して扱える DateTime に変換する」ことです。

このユーティリティを持っておくと、
日付入力まわりのバグが激減し、
画面・API・DB のすべてで一貫したチェックができるようになります。

C#C#
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました