C#を使用したアプリケーション開発において、日付や時刻の操作は非常に頻繁に行われる処理の一つです。

特に「曜日」の取得や判定は、予約システム、カレンダーアプリ、業務レポートの自動作成など、幅広いシーンで求められます。

本記事では、C#の標準ライブラリを活用して、効率的かつ正確に曜日を扱うためのテクニックを網羅的に紹介します。

初心者の方から実務レベルのエンジニアまで役立つ、具体的なコード例を交えながら進めていきましょう。

C#における曜日の基本概念とDayOfWeek列挙型

C#で曜日を扱うための中心的な役割を担うのが、System.DayOfWeek列挙型です。

この列挙型は、日曜日から土曜日までの7つの曜日を数値として定義しています。

DateTime構造体や、より新しいDateOnly構造体のプロパティを参照すると、この列挙型の値が返されます。

まずは、DayOfWeek列挙型がどのような値を持っているかを確認しておきましょう。

定数名数値意味
DayOfWeek.Sunday0日曜日
DayOfWeek.Monday1月曜日
DayOfWeek.Tuesday2火曜日
DayOfWeek.Wednesday3水曜日
DayOfWeek.Thursday4木曜日
DayOfWeek.Friday5金曜日
DayOfWeek.Saturday6土曜日

C#では日曜日が「0」から始まるという点は、配列のインデックス計算などでも重要なポイントとなります。

DateTime構造体から現在の曜日を取得する

現在の日付から曜日を取得する最もシンプルな方法は、DateTime.NowまたはDateTime.Todayプロパティを使用することです。

以下のサンプルコードでは、本日の日付情報を取得し、その曜日を表示しています。

C#
using System;

class Program
{
    static void Main()
    {
        // 現在の日時を取得
        DateTime now = DateTime.Now;

        // DayOfWeekプロパティから曜日を取得
        DayOfWeek todayEnum = now.DayOfWeek;

        // 列挙型の名前と数値を表示
        Console.WriteLine($"本日の曜日 (列挙型): {todayEnum}");
        Console.WriteLine($"本日の曜日 (数値): {(int)todayEnum}");
    }
}
実行結果
本日の曜日 (列挙型): Thursday
本日の曜日 (数値): 4

このように、DayOfWeekプロパティにアクセスするだけで簡単に列挙型の値が取得できます。

整数値として扱いたい場合は、(int)によるキャストを行うことで数値を取り出すことが可能です。

曜日を判定・活用する実践的なロジック

取得した曜日データを用いて、特定のロジックを実装するケースは非常に多いです。

例えば、「土日であれば休日処理を行う」といった分岐処理はビジネスアプリケーションの定番です。

特定の曜日を判定する方法

曜日の判定には、単純な比較演算子 == を使用します。

以下の例では、今日が土曜日または日曜日であるかどうかを判定しています。

C#
DateTime today = DateTime.Today;

// 土日判定のロジック
if (today.DayOfWeek == DayOfWeek.Saturday || today.DayOfWeek == DayOfWeek.Sunday)
{
    Console.WriteLine("本日はお休みです。");
}
else
{
    Console.WriteLine("本日は営業日です。");
}

このように、DayOfWeek列挙型の定数と比較することで、可読性の高いコードを記述できます。

数値を直接 if (day == 0) のように比較することも可能ですが、コードの意図が伝わりにくくなるため、列挙型の定数を使用することが推奨されます

switch式を用いた効率的な曜日分岐

最新のC#では、switch文よりも簡潔に記述できる「switch式」を活用するのが一般的です。

各曜日に応じて異なるメッセージを表示するロジックをスマートに記述してみましょう。

C#
DayOfWeek day = DateTime.Today.DayOfWeek;

string message = day switch
{
    DayOfWeek.Monday    => "週の始まりです。頑張りましょう。",
    DayOfWeek.Friday    => "週の終わりが見えてきました。",
    DayOfWeek.Saturday  => "週末を楽しみましょう。",
    DayOfWeek.Sunday    => "ゆっくり休んで備えましょう。",
    _                   => "今日も一日着実に進みましょう。" // 火・水・木に該当
};

Console.WriteLine(message);

この記述方法により、複雑な分岐も一目で理解できる綺麗な構造になります。

アンダースコア _ はデフォルト(いずれにも該当しない場合)を意味し、コードの安全性を高めてくれます。

曜日を日本語で表示する方法

DayOfWeekをそのまま文字列に変換すると「Monday」のような英語表記になります。

しかし、日本向けのアプリケーションでは「月曜日」や「(月)」といった日本語表記が欠かせません。

ToStringメソッドと書式指定子による変換

最も手軽な方法は、DateTime.ToStringメソッドに特定の書式指定子を渡すことです。

日本語環境であれば、デフォルトで日本語の曜日が出力されますが、明示的にカルチャを指定するのが確実です。

C#
using System.Globalization;

DateTime date = DateTime.Now;

// "dddd" は 「月曜日」 の形式
string fullDay = date.ToString("dddd", new CultureInfo("ja-JP"));

// "ddd" は 「月」 の形式
string shortDay = date.ToString("ddd", new CultureInfo("ja-JP"));

Console.WriteLine($"長い形式: {fullDay}");
Console.WriteLine($"短い形式: {shortDay}");
実行結果
長い形式: 木曜日
短い形式: 木

new CultureInfo("ja-JP")を指定することで、実行環境の設定に左右されず、常に日本語で取得できるようになります。

これは、サーバーが海外にあるクラウド環境などで特に重要なテクニックです。

配列を使用した独自の曜日表記カスタマイズ

標準の書式以外にも、「(月)」や「【Mon】」など、プロジェクト固有のフォーマットが必要な場合があります。

その場合は、文字列配列を定義して、DayOfWeekの数値インデックスを利用するのが効率的です。

C#
string[] customDays = { "日", "月", "火", "水", "木", "金", "土" };
DayOfWeek day = DateTime.Today.DayOfWeek;

// DayOfWeekをintにキャストしてインデックスとして使用
string displayDay = $"({customDays[(int)day]})";

Console.WriteLine($"本日の表示: {displayDay}");

この方法は処理速度が非常に速く、メモリ消費も抑えられるため、大量のデータをループ内で処理する場合に適しています。

応用:特定の曜日を計算・操作するテクニック

曜日の操作は単なる取得にとどまらず、特定の日付を導き出す計算にも応用されます。

次の月曜日を求めるアルゴリズム

「今日から見て次の月曜日は何日か?

」といった計算は、スケジュール管理ソフトなどで頻出します。

以下のロジックでは、曜日の差分を計算して次の月曜日を導き出しています。

C#
public static DateTime GetNextMonday(DateTime start)
{
    // 今日の曜日から月曜日(1)までの日数を計算
    int daysUntilMonday = ((int)DayOfWeek.Monday - (int)start.DayOfWeek + 7) % 7;

    // もし今日が月曜日なら、次の月曜日(7日後)にする場合は以下のように調整
    if (daysUntilMonday == 0) daysUntilMonday = 7;

    return start.AddDays(daysUntilMonday);
}

剰余演算子 % を活用することで、曜日の周期性をシンプルに表現しています。

このように数値をベースとした計算を行うことで、ループを使わずに目的の日付を割り出せます。

指定した年月のすべての土曜日を抽出する

カレンダーの自動生成などで役立つ、特定の月の中から特定の曜日をすべてリストアップする方法を見てみましょう。

C#
int year = 2026;
int month = 5;
var saturdays = new System.Collections.Generic.List<DateTime>();

DateTime firstDay = new DateTime(year, month, 1);
int daysInMonth = DateTime.DaysInMonth(year, month);

for (int d = 0; d < daysInMonth; d++)
{
    DateTime current = firstDay.AddDays(d);
    if (current.DayOfWeek == DayOfWeek.Saturday)
    {
        saturdays.Add(current);
    }
}

Console.WriteLine($"{year}年{month}月の土曜日:");
saturdays.ForEach(s => Console.WriteLine(s.ToShortDateString()));

DateTime.DaysInMonthを使用することで、月ごとの日数の違い(28日〜31日)を自動的に考慮した安全なループ処理が可能です。

最新の.NETにおける曜日の扱い

近年、.NETの進化に伴い、日付の扱い方もよりモダンで厳密なものへと変化しています。

DateOnly型の活用

.NET 6から導入されたDateOnly構造体は、時刻情報を持たない日付専用の型です。

「誕生日」や「記念日」といった、時刻が不要なデータに対して非常に有用であり、曜日も同様に取得できます。

C#
DateOnly birthday = new DateOnly(1995, 10, 15);
DayOfWeek birthDayOfWeek = birthday.DayOfWeek;

Console.WriteLine($"誕生日の曜日: {birthDayOfWeek}");

DateTime型と比較してメモリ使用量が少なく、意図しないタイムゾーンの影響も受けないため、積極的に活用すべき型と言えます。

タイムゾーンを考慮した曜日の取得

グローバル展開されるシステムでは、サーバーの時刻ではなく「特定の地域の現在時刻」における曜日が必要になります。

TimeZoneInfoクラスを併用することで、正確なローカル曜日を取得できます。

C#
DateTime utcNow = DateTime.UtcNow;
TimeZoneInfo jstZone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
DateTime jstTime = TimeZoneInfo.ConvertTimeFromUtc(utcNow, jstZone);

Console.WriteLine($"東京の現在曜日: {jstTime.DayOfWeek}");

サーバー時刻がUTC(世界標準時)に設定されている場合、日付が変わるタイミングが日本とずれるため、この考慮は不可欠です。

まとめ

C#における曜日の操作は、基本となるDayOfWeek列挙型の理解から始まります。

標準のDateTimeや最新のDateOnlyを活用することで、曜日の判定や計算を安全に行うことが可能です。

また、日本語表示においてはCultureInfoを用いた書式指定や、配列によるカスタマイズが非常に有効な手段となります。

本記事で紹介したテクニックを組み合わせることで、ユーザーにとって使いやすく、かつ保守性の高い日付処理ロジックを構築できるでしょう。

まずはシンプルな判定から始めて、徐々に高度な日付計算へと応用を広げてみてください。