CodeGym /コース /C# SELF /計算と日付・時間のための補助クラス

計算と日付・時間のための補助クラス

C# SELF
レベル 15 , レッスン 4
使用可能

1. 日付と時間を扱うときの基本タスク

日付や時間の扱いって、ベテラン開発者でもちょっと(いや、かなり?)パニックになることあるよね。日付の比較、間隔の計算、日/月/年の加減算、年齢の計算、曜日の判定…いろいろやることがある。

こういうのは、タスクトラッカーやカレンダー、会員権やサブスクの管理、ファイナンス計算、統計レポート、そしてもちろん面接の課題(例えば「2つの日付の間の営業日数を計算せよ」みたいなやつ)でよく出てくるよ。

C#.NETには、こういうタスク用の組み込みクラスやメソッドがちゃんとある。しかも、ほとんどの計算はオブジェクト指向で、安全で分かりやすいAPIでできるんだ。

2. TimeSpan構造体 — 時間の間隔を測る

まずはTimeSpan構造体から始めよう。これは「時間のかたまり」みたいなもので、例えば5日、3時間、7分、21秒みたいな感じ。

TimeSpanをどうやって作る?

2つの日付を「引き算」してもいいし、明示的に作ってもOK:

// 2つの日付の差は必ずTimeSpanになるよ!
DateTime start = new DateTime(2025, 5, 1, 7, 0, 0);
DateTime end = new DateTime(2025, 5, 2, 11, 30, 0);

TimeSpan duration = end - start; // 完全にマジック!
Console.WriteLine(duration); // 1.04:30:00 (1日、4時間、30分)

コンストラクタのパラメータでTimeSpanを明示的に作ることもできる:

TimeSpan span = new TimeSpan(2, 14, 18, 0); // 2日、14時間、18分、0秒
Console.WriteLine(span); // 2.14:18:00

別の作り方として、静的メソッドを使うと読みやすいことが多い:

TimeSpan fiveMinutes = TimeSpan.FromMinutes(5);
TimeSpan twoHours = TimeSpan.FromHours(2);
TimeSpan oneWeek = TimeSpan.FromDays(7);

TimeSpanにはどんなプロパティがある?

プロパティ 説明
Days
日数(整数)
Hours
時間部分
Minutes
分部分
Seconds
秒部分
TotalDays
日数(小数)
TotalHours
時間数(小数)
TotalMinutes
分数(小数)
TotalSeconds
秒数(小数)
Console.WriteLine($"日数: {duration.Days}, 合計時間: {duration.TotalHours}");

日付にTimeSpanを足したり引いたりするには?

DateTime now = DateTime.Now;
DateTime future = now.Add(duration); // nowにdurationを足す
DateTime past = now.Subtract(TimeSpan.FromDays(10)); // 10日前

Console.WriteLine(future);
Console.WriteLine(past);

3. 日付計算機:日付の差を計算しよう

これはほぼいつでも役立つスキル。例えば、誰かが「休みまであと何日?」とか「無料期間はいつ終わる?」とか知りたいときに使える。

DateTime today = DateTime.Today;
DateTime vacation = new DateTime(2025, 8, 1);
TimeSpan untilVacation = vacation - today;

Console.WriteLine($"休みまであと{untilVacation.Days}日だよ!");

注意:引き算に「日付」だけ(DateTime.DateDateTime.Today経由)を使うと、結果は必ず整数の日数になる。でも、どっちかに時間が入ってると、小数になるよ。


int days = (vacation - today).TotalDays; // コンパイルエラー! TotalDaysはdouble型

整数が欲しいなら、.Daysを使うか、(int)TotalDaysでキャストしよう。

4. 時間の加減算:AddDays, AddMonths, AddHoursなど

C#なら、月ごとの日数やうるう年の計算とか、面倒なことは手動でやらなくていい。こうやって使うだけ:

DateTime orderDate = new DateTime(2024, 4, 20);
DateTime deliveryDate = orderDate.AddDays(14); // 2週間後

Console.WriteLine($"商品は{deliveryDate.ToShortDateString()}に届くよ");
メソッド 何を足す(負数なら引く)
AddDays(double)
日(小数もOK、例:1.5日)
AddMonths(int)
月(自動で月の日数を考慮)
AddYears(int)
年(うるう年も考慮)
AddHours(double)
時間
AddMinutes(double)
AddSeconds(double)
DateTime birthday = new DateTime(2000, 2, 29);
DateTime nextYear = birthday.AddYears(1); // 2001-02-28(29日じゃない、2001年はうるう年じゃないから)
Console.WriteLine(nextYear.ToShortDateString()); // 28.02.2001

忘れずに:これらのメソッドは新しい日付インスタンスを返すだけで、元の日付は変わらないよ!

var dt = DateTime.Now;
dt.AddDays(5); // これはdtを変えない!
dt = dt.AddDays(5); // これでやっと変わる

5. 計算用の補助メソッド

曜日の計算

たいていは.DayOfWeekプロパティを使えばOK:

DateTime examDate = new DateTime(2025, 6, 19);
DayOfWeek day = examDate.DayOfWeek;
Console.WriteLine(day); // Wednesday

整数に変換することもできる:

int number = (int)day; // Sunday == 0, Monday == 1, みたいな感じ

「今日」「昨日」「明日」のチェック

シンプルな比較でOK:

DateTime date = new DateTime(2025, 6, 18);

if (date.Date == DateTime.Today)
    Console.WriteLine("今日だよ!");
else if (date.Date == DateTime.Today.AddDays(-1))
    Console.WriteLine("昨日だよ!");
else if (date.Date == DateTime.Today.AddDays(1))
    Console.WriteLine("明日だよ!");

年齢の計算

一番よくあるタスクの一つが、人の年齢をちゃんと計算すること。単純に年を引くだけじゃダメな場合が多い:

public static int CalculateAge(DateTime birthDate, DateTime currentDate)
{
    int age = currentDate.Year - birthDate.Year;
    
    // 今年まだ誕生日が来てなかったら
    if (currentDate.Month < birthDate.Month || 
        (currentDate.Month == birthDate.Month && currentDate.Day < birthDate.Day))
    {
        age--;
    }
    
    return age;
}

// 使い方
DateTime birth = new DateTime(1990, 8, 15);
DateTime today = DateTime.Today;
int age = CalculateAge(birth, today);
Console.WriteLine($"年齢: {age}歳");

営業日の計算

日付の間の営業日数(週末を除く)を計算したいことも多いよね:

public static int CountWorkingDays(DateTime startDate, DateTime endDate)
{
    int workingDays = 0;
    DateTime current = startDate;
    
    while (current <= endDate)
    {
        if (current.DayOfWeek != DayOfWeek.Saturday && 
            current.DayOfWeek != DayOfWeek.Sunday)
        {
            workingDays++;
        }
        current = current.AddDays(1);
    }
    
    return workingDays;
}

6. 主なクラスの関係

graph TD
    A(DateTime) --引き算--> B(TimeSpan)
    A2(DateTime) --AddDays, AddMonths--> A
    A --ToLocalTime/ToUniversalTime--> C(DateTimeOffset)
    D(DateOnly) --ToDateTime--> A
    E(TimeOnly) --ToTimeSpan--> B
    A --DayOfWeek, Day, Month, Year--> F(数値プロパティ)
    B(TimeSpan) --TotalDays, TotalHours, ...--> G(期間プロパティ)

7. クイックリファレンス:「こうしたいときは…」

やりたいこと 使うもの
日付の差を知りたい
TimeSpan duration = d2 - d1
(d2 - d1).Days
日付に2週間足したい
date.AddDays(14)
date.AddDays(14)
年齢を計算したい
.Year
と月/日のチェック
上のセクション参照
日付だけ取得/設定したい
DateOnly
DateOnly.FromDateTime(DateTime.Now)
時間だけ取得/設定したい
TimeOnly
TimeOnly.FromDateTime(DateTime.Now)
日付を比較したい 演算子
<
,
>
,
==
,
.CompareTo()
if (d1 < d2) ...
他のタイムゾーンに変換したい
DateTimeOffset + ToOffset
dto.ToOffset(TimeSpan.FromHours(3))
年の週番号を知りたい
Calendar.GetWeekOfYear()
ドキュメント参照
曜日を知りたい
date.DayOfWeek
営業日を数えたい
DayOfWeek
でチェックするループ
上のセクション参照
2
タスク
C# SELF, レベル 15, レッスン 4
ロック未解除
日付の差を計算しよう
日付の差を計算しよう
2
タスク
C# SELF, レベル 15, レッスン 4
ロック未解除
曜日を判定しよう
曜日を判定しよう
1
アンケート/クイズ
日付の扱い、レベル 15、レッスン 4
使用不可
日付の扱い
日付、時間、タイムゾーンの扱い方
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION