簡介
DateTime 是 System 命名空間中用於表示日期和時間的結構體,廣泛用於處理時間相關的操作,如存儲、計算、格式化等。
DateTime 結構概述
// 時間單位轉換
1 秒 = 10,000,000 Ticks
1 毫秒 = 10,000 Ticks
1 分鐘 = 600,000,000 Ticks
主要功能
表示日期和時間:
- 包含年、月、日、時、分、秒、毫秒。
- 支持
Kind 屬性(Utc、Local、Unspecified)。
時間操作:
- 比較:
Compare、CompareTo。
- 運算:加減時間(
AddDays、AddHours 等)。
- 時間差:
Subtract 返回 TimeSpan。
格式化:
- 使用
ToString 格式化(如 "yyyy-MM-dd HH:mm:ss")。
- 支持區域性(
CultureInfo)。
轉換:
靜態屬性:
DateTime.Now:本地時間。
DateTime.UtcNow:UTC 時間。
DateTime.Today:當前日期(時間為 00:00:00)。
核心屬性
| 屬性 |
説明 |
Now |
返回本地時區當前時間 |
UtcNow |
返回 UTC 當前時間 |
Today |
返回本地時區當前日期(00:00:00 時分秒) |
Date |
取當前實例的日期部分,時間部分置 00:00:00 |
Year, Month, Day |
年、月、日 |
Hour, Minute, Second, Millisecond |
小時、分鐘、秒、毫秒 |
DayOfWeek |
星期枚舉(DayOfWeek.Monday…) |
DayOfYear |
年內天數(1–366) |
Kind |
時間種類(Utc/Local/Unspecified) |
Ticks |
自 0001-01-01 00:00:00 起的刻度數(100ns 為單位) |
var dt = DateTime.Now;
Console.WriteLine($"{dt.Year}-{dt.Month}-{dt.Day} {dt.Hour}:{dt.Minute}:{dt.Second}, Kind={dt.Kind}");
構造與轉換
構造器
// 指定年月日時分秒
var dt1 = new DateTime(2025, 8, 8, 14, 30, 0);
// 指定 Kind
var dt2 = new DateTime(2025,8,8,14,30,0, DateTimeKind.Utc);
從 ticks
var dtTicks = new DateTime(637632000000000000L);
與 Unix 時間戳
// DateTime <-> Unix seconds
var unixEpoch = DateTimeOffset.FromUnixTimeSeconds(0).UtcDateTime;
long toUnix = ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds();
與 DateTimeOffset
DateTimeOffset 推薦用於跨時區場景,包含一個偏移量字段,且不樸素依賴 Kind。
- 從
DateTime 轉換:
var dto = new DateTimeOffset(dt); // 按本地偏移
var dtoUtc = new DateTimeOffset(dt, TimeSpan.Zero);
特殊日期獲取
DateTime today = DateTime.Today; // 今天的午夜時間
DateTime min = DateTime.MinValue;
DateTime max = DateTime.MaxValue;
DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTimeKind 與時區處理
DateTimeKind 枚舉
public enum DateTimeKind
{
Unspecified = 0, // 未指定時區(默認)
Utc = 1, // UTC時間
Local = 2 // 本地時間
}
時區轉換最佳實踐
// 創建帶時區信息的時間
DateTime utcTime = new DateTime(2023, 10, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime localTime = new DateTime(2023, 10, 1, 8, 0, 0, DateTimeKind.Local);
// 時區轉換
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("China Standard Time");
// UTC轉本地時間
DateTime utcToChina = TimeZoneInfo.ConvertTimeFromUtc(utcTime, tz);
// 本地時間轉UTC
DateTime chinaToUtc = TimeZoneInfo.ConvertTimeToUtc(localTime, tz);
// 跨時區轉換
TimeZoneInfo nyTz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime chinaToNy = TimeZoneInfo.ConvertTime(localTime, tz, nyTz);
格式化與解析
標準格式化字符串
| 格式符 |
説明 |
示例輸出 |
| "d" |
短日期 |
2023-06-15 |
| "D" |
長日期 |
2023年6月15日 |
| "t" |
短時間 |
14:30 |
| "T" |
長時間 |
14:30:45 |
| "f" |
完整日期/時間 |
2023年6月15日 14:30 |
| "F" |
完整格式 |
2023年6月15日 14:30:45 |
| "g" |
常規短格式 |
2023-06-15 14:30 |
| "G" |
常規長格式 |
2023-06-15 14:30:45 |
| "s" |
可排序格式 |
2023-06-15T14:30:45 |
| "u" |
通用可排序 |
2023-06-15 14:30:45Z |
| "U" |
UTC完整格式 |
2023年6月15日 6:30:45 |
格式化
dt.ToString("o"); // ISO 8601 完整格式:2025-08-08T14:30:00.0000000Z
dt.ToString("s"); // 可排序格式:2025-08-08T14:30:00
dt.ToString("G"); // 默認長日期+長時間
dt.ToString("d"); // "2023/10/1"(短日期)
dt.ToString("D"); // "2023年10月1日"(長日期)
dt.ToString("t"); // "14:30"(短時間)
dt.ToString("T"); // "14:30:00"(長時間)
dt.ToString("yyyy-MM-dd HH:mm:ss"); // 2025-08-08 14:30:00
dt.ToString("yyyy-MM-dd HH:mm:ss.fff"); // 帶毫秒
dt.ToString("dddd, MMM d yyyy"); // 星期幾, 月 日 年
解析
DateTime.Parse("2025-08-08 14:30");
DateTime.TryParse("2025-08-08", out var dt);
DateTime.ParseExact("08/08/2025", "MM/dd/yyyy", CultureInfo.InvariantCulture);
DateTime.TryParseExact(input, new[] {"yyyy-MM-dd","MM/dd/yyyy"},
CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
日期時間組件訪問
屬性訪問
DateTime dt = new DateTime(2023, 10, 5, 14, 30, 45, 123);
int year = dt.Year; // 2023
int month = dt.Month; // 10
int day = dt.Day; // 5
int hour = dt.Hour; // 14
int minute = dt.Minute; // 30
int second = dt.Second; // 45
int millisecond = dt.Millisecond; // 123
long ticks = dt.Ticks; // 638,000,000,000,000,000 + ...
DayOfWeek dayOfWeek = dt.DayOfWeek; // DayOfWeek.Thursday
int dayOfYear = dt.DayOfYear; // 278 (10月5日是2023年第278天)
日期計算輔助
DateTime dt = new DateTime(2023, 2, 15);
// 獲取月份天數
int daysInFeb = DateTime.DaysInMonth(2023, 2); // 28
// 判斷閏年
bool isLeap2023 = DateTime.IsLeapYear(2023); // false
bool isLeap2024 = DateTime.IsLeapYear(2024); // true
// 獲取月份首日和末日
DateTime firstDayOfMonth = new DateTime(dt.Year, dt.Month, 1);
DateTime lastDayOfMonth = new DateTime(dt.Year, dt.Month,
DateTime.DaysInMonth(dt.Year, dt.Month));
日期時間運算與比較
算術運算
DateTime now = DateTime.Now;
// 加法
DateTime tomorrow = now.AddDays(1);
DateTime nextHour = now.AddHours(1);
DateTime nextMinute = now.AddMinutes(1);
// 減法
DateTime yesterday = now.AddDays(-1);
DateTime lastWeek = now.AddDays(-7);
// 時間跨度計算
DateTime start = new DateTime(2023, 1, 1);
DateTime end = new DateTime(2023, 12, 31);
TimeSpan duration = end - start; // 364天
// Ticks運算
DateTime preciseTime = now.AddTicks(50000); // 增加5毫秒
比較操作
DateTime dateA = new DateTime(2023, 6, 15);
DateTime dateB = new DateTime(2023, 6, 20);
// 比較方法
int compareResult = DateTime.Compare(dateA, dateB);
// <0: dateA < dateB
// =0: 相等
// >0: dateA > dateB
// 運算符重載
bool isBefore = dateA < dateB; // true
bool isAfter = dateA > dateB; // false
bool isSame = dateA == dateB; // false
// 範圍檢查
bool isInRange = dateA >= start && dateA <= end;
DateTime 與相關類型對比
| 特性 |
DateTime |
DateTimeOffset |
TimeOnly |
DateOnly |
NodaTime |
| 時區支持 |
弱 |
強(偏移量) |
無 |
無 |
強 |
| 日期部分 |
需要計算 |
需要計算 |
無 |
有 |
有 |
| 時間部分 |
有 |
有 |
有 |
無 |
有 |
| 精度 |
100ns |
100ns |
100ns |
天 |
1ns |
| 序列化 |
有問題 |
安全 |
安全 |
安全 |
安全 |
| 範圍 |
0001-9999 |
0001-9999 |
00:00-24:00 |
0001-9999 |
無限 |
| .NET版本 |
1.0+ |
2.0+ |
6.0+ |
6.0+ |
NuGet包 |
最佳實踐總結
存儲原則:
- 始終以
UTC 時間存儲
- 僅在顯示時轉換為本地時間
序列化準則:
// 使用ISO 8601格式
DateTime.UtcNow.ToString("O"); // 2023-10-05T06:30:45.1234567Z
時區處理:
- 使用
DateTimeOffset 替代 DateTime
- 複雜時區需求使用
NodaTime 或 TimeZoneInfo
日期/時間分離:
// .NET 6+ 推薦
DateOnly birthday = new DateOnly(1990, 5, 15);
TimeOnly meetingTime = new TimeOnly(14, 30);
性能敏感場景:
- 避免重複調用
DateTime.Now/UtcNow
- 預計算靜態日期值
- 高精度計時用
Stopwatch
資源和文檔
DateTime:https://learn.microsoft.com/en-us/dotnet/api/system.datetime
TimeZoneInfo:https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo
ASP.NET Core:https://learn.microsoft.com/en-us/aspnet/core/