C# Tips | 日付・時間処理:日付減算

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

はじめに 「日付減算」は“差を測る”だけじゃなく“◯日前”も作れる道具

日付の「減算」と聞くと、
まず思い浮かぶのは「2つの日付の差を取る」ことだと思います。

でも実務ではそれだけでなく、

  • 「◯日前に戻す」(有効期限の開始日を求める)
  • 「締切まであと何日か計算する」
  • 「処理時間を測る」

といった場面でも、日付減算は頻繁に登場します。

C# では、

  • DateTime - DateTimeTimeSpan(差)
  • DateTime.AddDays(-n) → n日前
  • TimeSpan を使った柔軟な差の扱い

という形で、直感的に書けます。

ここから、
基本の引き算 → 差分の読み方 → ◯日前を作る書き方 → 実務ユーティリティ化
という流れで、初心者向けにかみ砕いて説明していきます。


基本:DateTime - DateTime で差を取る

差は TimeSpan という「時間の長さ」になる

2つの DateTime を引き算すると、結果は TimeSpan になります。

using System;

DateTime start = new DateTime(2026, 2, 10, 9, 0, 0);
DateTime end   = new DateTime(2026, 2, 10, 18, 30, 0);

TimeSpan diff = end - start;

Console.WriteLine(diff);              // 09:30:00
Console.WriteLine(diff.TotalHours);   // 9.5
Console.WriteLine(diff.TotalMinutes); // 570
C#

ここで大事なのは、

  • diff 自体は「9時間30分」という“時間の長さ”
  • TotalHoursTotalMinutes で「何時間分か」「何分分か」を数値として取り出せる

という点です。

「締切まであと何時間?」
「処理に何ミリ秒かかった?」
といった計算は、すべてこの TimeSpan から読み取ります。

日数の差を取りたいとき

日数の差も同じです。

DateTime d1 = new DateTime(2026, 2, 1);
DateTime d2 = new DateTime(2026, 2, 10);

TimeSpan diff = d2 - d1;

Console.WriteLine(diff.Days);        // 9
Console.WriteLine(diff.TotalDays);   // 9
C#

Days は「切り捨てた日数」、
TotalDays は「小数も含めた日数」です。

時間も含めて差を取りたいときは TotalDays
「何日違うか」だけ知りたいときは Days
という使い分けをすると分かりやすいです。


「◯日前」「◯時間前」を作る減算

AddDays(-n) は「n日前」

日付減算は、
「今から◯日前に戻す」という形でもよく使います。

DateTime now = DateTime.Now;

DateTime threeDaysAgo = now.AddDays(-3);
DateTime oneHourAgo   = now.AddHours(-1);

Console.WriteLine(now);          // 2026/02/10 20:00:00 など
Console.WriteLine(threeDaysAgo); // 2026/02/07 20:00:00
Console.WriteLine(oneHourAgo);   // 2026/02/10 19:00:00
C#

AddDays(3) が「3日後」なら、
AddDays(-3) は「3日前」です。

「◯日前」「◯時間前」は、
専用のメソッドがあるわけではなく、
「加算メソッドにマイナスを渡す」=減算
という形で書きます。

「◯ヶ月前」は AddMonths(-n)

月単位の減算も同じです。

DateTime d = new DateTime(2026, 2, 10);

DateTime oneMonthAgo = d.AddMonths(-1);

Console.WriteLine(oneMonthAgo); // 2026/01/10
C#

ここでも、末日近辺の“丸めルール”は加算と同じです。

DateTime endOfMarch = new DateTime(2026, 3, 31);

DateTime oneMonthAgo2 = endOfMarch.AddMonths(-1);

Console.WriteLine(oneMonthAgo2); // 2026/02/28(うるう年でなければ)
C#

「存在しない日付」は、その月の末日に丸められます。


実務でよくある「差分」の読み方

締切まであと何日かを計算する

例えば、「締切日時」と「現在日時」があって、
「あと何日あるか」を知りたいケースです。

DateTime now      = DateTime.Now;
DateTime deadline = new DateTime(2026, 2, 20, 23, 59, 59);

TimeSpan diff = deadline - now;

Console.WriteLine($"残り日数: {diff.TotalDays} 日");
Console.WriteLine($"残り時間: {diff.TotalHours} 時間");
C#

ここで重要なのは、
「締切 − 現在」 の順で引き算することです。

逆にすると符号が反転します。

TimeSpan diff2 = now - deadline;

Console.WriteLine(diff2.TotalDays); // マイナスの値(締切を過ぎている)
C#

「過ぎているかどうか」を判定したいときは、
deadline < now のように DateTime 同士を比較するほうが素直です。

差分は「どれくらい離れているか」を知るために使う、
というイメージを持っておくと整理しやすいです。

処理時間を測る(簡易版)

処理の前後で DateTime を取っておき、
差を取ることで「何ミリ秒かかったか」を測ることもできます。

DateTime start = DateTime.UtcNow;

// 何か重い処理
DoSomething();

DateTime end = DateTime.UtcNow;

TimeSpan elapsed = end - start;

Console.WriteLine($"処理時間: {elapsed.TotalMilliseconds} ms");
C#

本格的には Stopwatch クラスを使うのが定番ですが、
「とりあえずざっくり測りたい」なら、このパターンでも十分役に立ちます。


実務ユーティリティとしてまとめる

「2つの日付の差」を分かりやすく返す

差分の計算をあちこちで書くより、
ユーティリティにしてしまうと意図がはっきりします。

using System;

public readonly struct DateDiff
{
    public double TotalDays { get; }
    public double TotalHours { get; }
    public double TotalMinutes { get; }

    public DateDiff(TimeSpan span)
    {
        TotalDays    = span.TotalDays;
        TotalHours   = span.TotalHours;
        TotalMinutes = span.TotalMinutes;
    }
}

public static class DateDiffUtil
{
    public static DateDiff Between(DateTime from, DateTime to)
    {
        TimeSpan span = to - from;
        return new DateDiff(span);
    }

    public static DateTime DaysAgoFromNow(int days)
    {
        return DateTime.Now.AddDays(-days);
    }

    public static DateTime MonthsAgoFromNow(int months)
    {
        return DateTime.Now.AddMonths(-months);
    }
}
C#

使い方の例です。

DateTime start = new DateTime(2026, 2, 1);
DateTime end   = new DateTime(2026, 2, 10);

var diff = DateDiffUtil.Between(start, end);

Console.WriteLine(diff.TotalDays);   // 9
Console.WriteLine(diff.TotalHours);  // 216

DateTime sevenDaysAgo  = DateDiffUtil.DaysAgoFromNow(7);
DateTime twoMonthsAgo  = DateDiffUtil.MonthsAgoFromNow(2);

Console.WriteLine(sevenDaysAgo);
Console.WriteLine(twoMonthsAgo);
C#

「Between」「DaysAgoFromNow」「MonthsAgoFromNow」といった名前にしておくと、
コードを読むだけで「何をしたいのか」が伝わりやすくなります。


UTCとローカルの“時間軸”をそろえて減算する

片方がUTC、片方がローカルのまま引き算しない

DateTime 同士の引き算は、
同じ時間軸(両方UTC、または両方ローカル)で行うのが鉄則です。

片方が DateTimeKind.Utc、片方が DateTimeKind.Local のまま引き算すると、
内部的にはローカルに変換されますが、
意図しないズレを生む原因になります。

安全にやるなら、

  • どちらも ToUniversalTime() してから引き算
  • あるいはどちらも ToLocalTime() してから引き算

という形にそろえます。

DateTime aUtc = DateTime.UtcNow;
DateTime bUtc = someUtcTime;

TimeSpan diff = bUtc - aUtc; // 両方UTCなのでOK
C#

DateTimeOffset 同士なら、
オフセットを考慮した上で差分が取れるので、
タイムゾーンをまたぐシステムではこちらを使うのも有力です。


まとめ 「日付減算ユーティリティ」は“時間の距離感を数字にするものさし”

日付減算は、

  • 2つの日時の差を TimeSpan として測る
  • 「◯日前」「◯ヶ月前」を作る
  • 締切までの残り時間や処理時間を数値化する

といった場面で、業務ロジックの土台になります。

押さえておきたいポイントは、

  • DateTime - DateTime の結果は TimeSpan で、TotalDays / TotalHours / TotalMinutes などで数値として読めること。
  • 「◯日前」「◯時間前」は AddDays(-n) / AddHours(-n) のように、加算メソッドにマイナスを渡して書くこと。
  • 月単位の減算は AddMonths(-n) を使い、末日近辺では「存在しない日付はその月の末日に丸められる」ルールを理解しておくこと。
  • 差分を取るときは「どちらを引くか」(締切 − 現在 なのか、その逆なのか)を意識し、符号の意味を考えること。
  • UTCとローカルなど、時間軸の違う DateTime 同士をそのまま引き算せず、同じ基準にそろえてから差を取ること。

ここを押さえておくと、
「なんとなく引き算している」状態から一歩進んで、
“時間の距離感を正しく測れる、実務で使える日付減算ユーティリティ”を
自分のC#コードの中に自然に組み込めるようになっていきます。

タイトルとURLをコピーしました