簡介
DateTimeOffset 是 System 命名空間中的結構體,用於表示特定時間點及其相對於協調世界時(UTC)的偏移量。相比 DateTime,它更適合處理跨時區場景,確保時間數據在全球化應用中的一致性和精確性。
- 定義:
System.DateTimeOffset 表示帶有固定時區偏移量的點時間。
- 用途:既保留了
UTC 時間戳,也攜帶了相對於 UTC 的偏移量(Offset),在分佈式、多時區場景下更可靠。
-
內部存儲:
DateTime _dateTime(Kind 固定為 Unspecified)
TimeSpan _offset(-14h 到 +14h 範圍)
var dto = new DateTimeOffset(2025, 8, 8, 14, 30, 0, TimeSpan.FromHours(+8));
graph TD
A[DateTimeOffset] --> B[DateTime]
A --> C[Offset]
B --> D[日期部分]
B --> E[時間部分]
C --> F[UTC偏移量]
DateTimeOffset 結構詳解
內部表示
public struct DateTimeOffset : IComparable, IFormattable, ...
{
private readonly DateTime _dateTime;
private readonly short _offsetMinutes;
// 屬性
public DateTime DateTime { get; } // 日期時間部分
public DateTime UtcDateTime { get; } // UTC 等效時間
public TimeSpan Offset { get; } // 偏移量
public long Ticks { get; } // 自 0001-01-01 的滴答數
public DateTime Date { get; } // 日期部分
public int Year { get; } // 年
// ... 其他屬性類似 DateTime
}
核心API
屬性
| 屬性 |
説明 |
DateTime |
去除偏移量的本地時間(DateTimeKind.Unspecified) |
UtcDateTime |
按 Offset 轉換到 UTC 的 DateTime(Kind.Utc) |
Offset |
相對於 UTC 的偏移量(TimeSpan) |
LocalDateTime |
按當前系統時區再次轉換的本地時間(DateTimeKind.Local) |
Date |
DateTime.Date 部分,保留偏移量 |
Year/Month/Day |
年、月、日 |
Hour/Minute/Second |
小時、分鐘、秒 |
Ticks |
自 0001-01-01T00:00:00 起的刻度數(100 ns 為單位,不含偏移) |
Now |
當前本地時間帶本地偏移(等同 new DateTimeOffset(DateTime.Now)) |
UtcNow |
當前 UTC 時間,偏移量為 TimeSpan.Zero |
方法
Add(TimeSpan):添加時間跨度。
AddDays(double)、AddHours(double) 等:添加特定單位。
Subtract(DateTimeOffset):計算時間差(返回 TimeSpan)。
ToString(string):格式化輸出。
ToUniversalTime():轉換為 UTC。
ToOffset(TimeSpan):轉換為指定偏移。
Parse(string)、TryParse(string, out DateTimeOffset):解析字符串。
靜態方法
DateTimeOffset.Compare(DateTimeOffset, DateTimeOffset):比較兩個時間。
DateTimeOffset.ParseExact(string, string, IFormatProvider):精確解析。
構造與轉換
常用構造器
// 指定本地時間和偏移
var dto1 = new DateTimeOffset(2025,8,8,14,30,0, TimeSpan.FromHours(+8));
// 從 DateTime 創建(注意 Kind)
var dtLocal = DateTime.Now; // Kind.Local
var dto2 = new DateTimeOffset(dtLocal);
// 從 UTC DateTime 創建
var dtUtc = DateTime.UtcNow;
var dto3 = new DateTimeOffset(dtUtc).ToOffset(TimeSpan.Zero);
偏移轉換
// 將 dto 轉到另一個時區偏移(僅改變 Offset,不更改瞬時時間)
var dtoTokyo = dto.ToOffset(TimeSpan.FromHours(+9));
// 獲取共同的絕對時刻
DateTimeOffset a = dto1, b = dtoTokyo;
bool sameInstant = a.ToUniversalTime() == b.ToUniversalTime(); // true
與 DateTime 相互轉換
// DateTimeOffset -> DateTime (Unspecified)
DateTime dtUnspecified = dto.DateTime;
// DateTimeOffset -> UTC DateTime
DateTime dtUtc = dto.UtcDateTime;
// DateTimeOffset -> Local DateTime
DateTime dtLocal2 = dto.LocalDateTime;
// DateTime -> DateTimeOffset
var dtoFromDt = new DateTimeOffset(dtUnspecified, TimeZoneInfo.Local.GetUtcOffset(dtUnspecified));
格式化與解析
標準格式字符串
| 格式符 |
説明 |
示例輸出 |
| "o" |
往返格式 |
2023-10-05T14:30:00.0000000+08:00 |
| "r" |
RFC1123 |
Thu, 05 Oct 2023 14:30:00 +0800 |
| "u" |
通用可排序 |
2023-10-05 06:30:00Z |
| "s" |
可排序 |
2023-10-05T14:30:00 |
| "g" |
常規短格式 |
10/5/2023 2:30 PM |
| "G" |
常規長格式 |
10/5/2023 2:30:00 PM |
格式化
dto.ToString("o"); // 2025-08-08T14:30:00.0000000+08:00
dto.ToString("u"); // 2025-08-08 14:30:00Z
dto.ToString("yyyy-MM-dd HH:mm zzz"); // 2025-08-08 14:30 +08:00
dto.ToString("yyyy-MM-dd HH:mm K"); // K 同 zzz
解析
DateTimeOffset.Parse("2025-08-08T14:30:00+08:00");
DateTimeOffset.TryParse("2025-08-08 06:30:00Z", out var dto);
ParseExact / TryParseExact
DateTimeOffset.ParseExact("2025/08/08 14:30 +0800",
"yyyy/MM/dd HH:mm zzz", CultureInfo.InvariantCulture);
DateTimeOffset.TryParseExact(input,
new[]{ "o","yyyy-MM-dd HH:mm zzz"},
CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dto);
比較與運算
var a = new DateTimeOffset(2025,8,8,10,0,0,TimeSpan.FromHours(+1));
var b = new DateTimeOffset(2025,8,8,18,0,0,TimeSpan.FromHours(+9));
// 絕對瞬時時間相同
bool eq = a.ToUniversalTime() == b.ToUniversalTime(); // true
// 差值
TimeSpan diff = b - a; // Zero
- 支持
+/- TimeSpan、- DateTimeOffset(結果 TimeSpan)
- 支持
Compare(), Equals(), 運算符 <, > 等基於 UTC 比較
與 DateTime 的比較
| 特性 |
DateTime |
DateTimeOffset |
| 時區信息 |
僅有 Kind,不含偏移量 |
明確定義了相對於 UTC 的偏移量 |
| 存儲一致性 |
若用本地 DateTime.Now 存庫,會丟失上下文 |
可存儲為 ISO 8601 帶偏移字符串,恢復無歧義 |
| 夏令時問題 |
依賴系統時區轉換,歧義轉化 |
偏移固定,不受夏令時影響 |
| 跨系統/跨語言互操作性 |
存 UTC 時需額外約定 |
標準化輸出帶偏移,易互操作 |
| 推薦用於多時區業務場景 |
較麻煩 |
首選 |
資源和文檔
DateTimeOffset:https://learn.microsoft.com/en-us/dotnet/api/system.datetimeo...
TimeZoneInfo:https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo