C# Tips | 日付・時間処理:閏年判定

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

はじめに:「閏年判定」は“2月29日があるかどうかを見抜く小さな知恵”

「この年は 2月29日があるのか?」
「2024年は閏年だけど、2100年は?」

カレンダーや日付計算を扱うシステムでは、
“閏年(うるう年)かどうか”を正しく判定できることがとても大事です。
特に「2月末日」を扱う処理(締め日・請求日・勤怠など)では、
閏年を間違えると、2月29日が存在しない年に日付を作ってしまう、といったバグにつながります。

C# には、実はすでに「閏年判定」の答えを教えてくれるメソッドが用意されています。
まずはそれを押さえたうえで、「中で何をしているのか」というルールもかみ砕いて説明していきます。


一番簡単な方法:DateTime.IsLeapYear を使う

たった1行で「その年が閏年かどうか」を判定できる

C# では、System.DateTime に静的メソッド IsLeapYear が用意されています。

bool isLeap = DateTime.IsLeapYear(2024);  // true
bool isLeap2 = DateTime.IsLeapYear(2025); // false
C#

このメソッドは、
「その年が閏年なら true、そうでなければ false」
を返してくれます。

例を少し増やしてみます。

Console.WriteLine(DateTime.IsLeapYear(2000)); // true
Console.WriteLine(DateTime.IsLeapYear(1900)); // false
Console.WriteLine(DateTime.IsLeapYear(2024)); // true
Console.WriteLine(DateTime.IsLeapYear(2100)); // false
C#

ここでの重要ポイントは、
「西暦の閏年ルール(100年ごと・400年ごとの例外)まで含めて、全部このメソッドが面倒を見てくれる」
ということです。
実務では、まずはこの DateTime.IsLeapYear を素直に使うのが一番安全です。


閏年のルールを“人間の言葉”で理解する

ルールを日本語で整理するとこうなる

C# の IsLeapYear が内部で使っているのは、
グレゴリオ暦の標準的な閏年ルールです。

年が 4 で割り切れる年は閏年
ただし、100 で割り切れる年は平年
ただし、400 で割り切れる年はやっぱり閏年

これを具体例で見るとイメージがつきやすいです。

2024年 → 4で割り切れる、100で割り切れない → 閏年
1900年 → 4で割り切れる、100でも割り切れる、400では割り切れない → 平年
2000年 → 4で割り切れる、100でも割り切れる、400でも割り切れる → 閏年

「100年ごとに一回、閏年を飛ばすけど、400年ごとにまた閏年に戻す」
というイメージです。


自分で閏年判定ロジックを書くとどうなるか

ルールをそのまま if 文に落とし込む

学習のために、IsLeapYear と同じ判定を自分で書いてみましょう。

public static bool IsLeapYearCustom(int year)
{
    if (year % 400 == 0)
    {
        return true;
    }

    if (year % 100 == 0)
    {
        return false;
    }

    if (year % 4 == 0)
    {
        return true;
    }

    return false;
}
C#

使い方の例です。

Console.WriteLine(IsLeapYearCustom(2000)); // true
Console.WriteLine(IsLeapYearCustom(1900)); // false
Console.WriteLine(IsLeapYearCustom(2024)); // true
Console.WriteLine(IsLeapYearCustom(2025)); // false
C#

ここでの重要ポイントは、
「400 → 100 → 4 の順にチェックしている」ことです。
400年の条件が一番“強い”ので最初に判定し、
次に 100年の例外、最後に 4年ごとの基本ルール、という順番にしています。


閏年判定を“実務でどう使うか”

2月の日数を求めるユーティリティ

実務でよくあるのが、「その年の2月が何日まであるか」を知りたいケースです。
例えば「月末締め」の処理で、2月の最終日を求めたいときなどです。

C# には、これもすでに便利メソッドがあります。

int daysInFeb2024 = DateTime.DaysInMonth(2024, 2); // 29
int daysInFeb2025 = DateTime.DaysInMonth(2025, 2); // 28
C#

DaysInMonth(year, month) は、
「その年のその月が何日まであるか」を返してくれます。
内部で閏年判定もしてくれるので、
「2月だけ特別扱いする」ようなコードを書く必要はありません。

もし自分で書くなら、こうなります。

public static int GetDaysInFebruary(int year)
{
    return DateTime.IsLeapYear(year) ? 29 : 28;
}
C#

ここでの重要ポイントは、
「閏年判定を直接使うよりも、DaysInMonth を使ったほうが、
“2月に限らずどの月でも正しい日数が取れる”ので実務では便利」
ということです。

「2月29日が有効な日付かどうか」をチェックする

ユーザーが「2024-02-29」と入力してきたとき、
それが有効な日付かどうかをチェックしたい場面もあります。

DateTime.TryParseExact を使えば、
閏年かどうかも含めて自動で判定してくれますが、
「年と月と日がバラバラに来る」ようなケースでは、
IsLeapYear と組み合わせてチェックすることもあります。

public static bool IsValidDate(int year, int month, int day)
{
    if (month < 1 || month > 12)
        return false;

    int daysInMonth = DateTime.DaysInMonth(year, month);
    return day >= 1 && day <= daysInMonth;
}
C#

このメソッドは、
「その年・その月に、その日付が存在するかどうか」を判定します。
内部で DaysInMonth を使っているので、
閏年かどうかも自動的に考慮されます。


実務で意識してほしいポイント

自前ロジックより「標準ライブラリ優先」で考える

閏年判定は、
自分で if 文を書いても実装できますが、
実務では基本的に

DateTime.IsLeapYear(year)
DateTime.DaysInMonth(year, month)

を優先して使うのがおすすめです。

理由はシンプルで、
「標準ライブラリはすでに十分テストされていて、
自前実装よりバグの可能性が低い」からです。

学習として自分で書いてみるのはとても良いですが、
プロダクションコードでは「標準のものを信頼して使う」癖をつけておくと、
余計なバグを減らせます。

「閏年を意識すべき処理」と「意識しなくていい処理」を分ける

すべての処理で閏年を意識する必要はありません。
例えば「日数差を TimeSpan で計算するだけ」の処理なら、
DateTime 同士の引き算に任せておけば、
内部で勝手に閏年も考慮してくれます。

一方で、
「2月末日を求める」「2月29日を含むかどうかで分岐する」
といった処理では、閏年を明示的に意識する必要があります。

どこで閏年を意識するかを見極めて、
必要なところだけ IsLeapYearDaysInMonth を使う、
というスタンスが実務的です。


まとめ:「閏年判定ユーティリティ」は“2月29日を正しく扱うための小さな土台”

閏年判定の本質は、
「その年に 2月29日が存在するかどうか」を、
正しく・一貫して判断できるようにすることです。

C# では、

DateTime.IsLeapYear(year) で、その年が閏年かどうかを一発で判定できる。
DateTime.DaysInMonth(year, month) を使えば、閏年も含めてその月の日数を安全に取得できる。
自前で書く場合は、「4で割り切れる年は閏年、ただし100で割り切れる年は平年、ただし400で割り切れる年は閏年」というルールを if 文に落とし込む。

このあたりを押さえておけば、
「2月だけ特別扱いしていてバグる」ようなコードから卒業して、
“カレンダーに強い C# プログラマー”に一歩近づけます。

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