はじめに:「閏年判定」は“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日を含むかどうかで分岐する」
といった処理では、閏年を明示的に意識する必要があります。
どこで閏年を意識するかを見極めて、
必要なところだけ IsLeapYear や DaysInMonth を使う、
というスタンスが実務的です。
まとめ:「閏年判定ユーティリティ」は“2月29日を正しく扱うための小さな土台”
閏年判定の本質は、
「その年に 2月29日が存在するかどうか」を、
正しく・一貫して判断できるようにすることです。
C# では、
DateTime.IsLeapYear(year) で、その年が閏年かどうかを一発で判定できる。DateTime.DaysInMonth(year, month) を使えば、閏年も含めてその月の日数を安全に取得できる。
自前で書く場合は、「4で割り切れる年は閏年、ただし100で割り切れる年は平年、ただし400で割り切れる年は閏年」というルールを if 文に落とし込む。
このあたりを押さえておけば、
「2月だけ特別扱いしていてバグる」ようなコードから卒業して、
“カレンダーに強い C# プログラマー”に一歩近づけます。
