推薦:DateTime.Compare 靜態方法,返回值語義清晰:
string t1 = "12:13", t2 = "14:14";
DateTime dt1 = DateTime.Parse(t1);
DateTime dt2 = DateTime.Parse(t2);
DateTime now = DateTime.Now;
int cmp = DateTime.Compare(dt1, dt2);
Console.WriteLine($"{t1} {(cmp > 0 ? ">" : cmp < 0 ? "<" : "=")} {t2}");
// 輸出: 12:13 < 14:14
cmp = DateTime.Compare(dt1, now);
Console.WriteLine($"{t1} {(cmp > 0 ? ">" : "<")} {now:HH:mm}");
// 輸出: 12:13 < 當前時間
替代方案: 直接用關係運算符(dt1 < dt2),編譯器內部同樣調用 Compare,代碼更直觀。
核心:TimeSpan 結構,精確到毫秒/微秒。
public static string GetTimeDifference(DateTime dt1, DateTime dt2) {
TimeSpan span = (dt1 > dt2) ? dt1 - dt2 : dt2 - dt1; // 或用 .Duration()
// TimeSpan ts = (dt1 - dt2).Duration(); // 一行搞定絕對值
return $"{span.Days}天 {span.Hours}小時 {span.Minutes}分鐘 {span.Seconds}秒 {span.Milliseconds}毫秒";
}
// 使用示例
DateTime start = new DateTime(2024, 1, 1, 10, 0, 0);
DateTime end = new DateTime(2024, 1, 3, 14, 30, 15);
Console.WriteLine(GetTimeDifference(start, end));
// 輸出: 2天 4小時 30分鐘 15秒 0毫秒
進階格式化: 自定義輸出(如僅顯示非零單位、總小時數等)。
核心:DateTime.Add/Subtract + TimeSpan
// 當前時間減去 36 天
TimeSpan offset = TimeSpan.FromDays(36); // 更語義化
DateTime past = DateTime.Now.Subtract(offset);
// 等價: DateTime past = DateTime.Now.AddDays(-36);
Console.WriteLine($"現在: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
Console.WriteLine($"36天前: {past:yyyy-MM-dd HH:mm:ss}");
// 更複雜:加 1年3個月10天5小時
DateTime future = DateTime.Now
.AddYears(1).AddMonths(3).AddDays(10).AddHours(5);
| 陷阱 | 正確做法 |
|---|---|
| 字符串直接比較("12:13" > "9:00" 為 false) | 先 Parse/TryParse 為 DateTime 再比較 |
| 忽略時區導致跨系統時間錯誤 | 統一用 UTC 存儲/傳輸,顯示時轉本地時區 |
| 用 Ticks 手動計算差值 | 直接用 - 運算符得 TimeSpan |
| 月份加減邊界(1月31日 +1月 = 2月28/29日) | 用 AddMonths 自動處理邊界 |
| 高頻循環中反復創建 TimeSpan | 預創建靜態 TimeSpan 常量 |
public static class DateTimeExtensions {
public static string ToFriendlySpan(this TimeSpan span) {
var parts = new List();
if (span.Days > 0) parts.Add($"{span.Days}天");
if (span.Hours > 0) parts.Add($"{span.Hours}小時");
if (span.Minutes > 0) parts.Add($"{span.Minutes}分鐘");
if (span.Seconds > 0) parts.Add($"{span.Seconds}秒");
if (span.Milliseconds > 0) parts.Add($"{span.Milliseconds}毫秒");
return parts.Count > 0 ? string.Join(" ", parts) : "0秒";
}
public static DateTime AtStartOfDay(this DateTime dt) => dt.Date;
public static DateTime AtEndOfDay(this DateTime dt) => dt.Date.AddDays(1).AddTicks(-1);
}