はじめに 「日付減算」は“差を測る”だけじゃなく“◯日前”も作れる道具
日付の「減算」と聞くと、
まず思い浮かぶのは「2つの日付の差を取る」ことだと思います。
でも実務ではそれだけでなく、
- 「◯日前に戻す」(有効期限の開始日を求める)
- 「締切まであと何日か計算する」
- 「処理時間を測る」
といった場面でも、日付減算は頻繁に登場します。
C# では、
DateTime - DateTime→TimeSpan(差)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分」という“時間の長さ”TotalHoursやTotalMinutesで「何時間分か」「何分分か」を数値として取り出せる
という点です。
「締切まであと何時間?」
「処理に何ミリ秒かかった?」
といった計算は、すべてこの 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#コードの中に自然に組み込めるようになっていきます。
