DateTime 格式化是 C# 開發中最高頻操作之一。本文整理**標準格式字串**、**自訂格式字串**、**常用屬性/方法**、**Parse/TryParse 最佳實務**與**時區/文化特性陷阱**,做成一張可離線備查的完整速查表。
單一字元,輸出固定模式,**受 CultureInfo.CurrentCulture 影響**。
| 格式 | 名稱 | 範例 (en-US) | 範例 (zh-TW) | 備註 |
|---|---|---|---|---|
d | 短日期 | 10/31/2023 | 2023/10/31 | |
D | 長日期 | Tuesday, October 31, 2023 | 2023年10月31日 | |
f | 完整日期時間 (短時間) | Tuesday, October 31, 2023 2:30 PM | 2023年10月31日 下午 02:30 | |
F | 完整日期時間 (長時間) | Tuesday, October 31, 2023 2:30:15 PM | 2023年10月31日 下午 02:30:15 | |
g | 一般 (短日期+短時間) | 10/31/2023 2:30 PM | 2023/10/31 下午 02:30 | |
G | 一般 (短日期+長時間) | 10/31/2023 2:30:15 PM | 2023/10/31 下午 02:30:15 | |
M, m | 月日 | October 31 | 10月31日 | |
Y, y | 年月 | October, 2023 | 2023年10月 | |
r, R | RFC1123 | Tue, 31 Oct 2023 14:30:15 GMT | (同左,固定英文) | **不受文化特性影響**,HTTP 標準 |
s | 可排序 (ISO 8601) | 2023-10-31T14:30:15 | (同左) | **不受文化特性影響**,DateTimeKind.Unspecified |
u | 通用可排序 (UTC) | 2023-10-31 14:30:15Z | (同左) | **不受文化特性影響**,末尾 Z 表 UTC |
U | 完整日期時間 (UTC) | Tuesday, October 31, 2023 6:30:15 AM | 2023年10月31日 上午 06:30:15 | 自動轉 UTC 再套用長日期格式 |
t | 短時間 | 2:30 PM | 下午 02:30 | |
T | 長時間 | 2:30:15 PM | 下午 02:30:15 | |
O, o | 往返格式 | 2023-10-31T14:30:15.1234567+08:00 | (同左) | **含毫秒、Kind、時差**,唯一能無損往返的格式 |
組合格式字元,**區分大小寫**,不受文化特性影響 (除非用 DateTimeFormatInfo)。
| 符號 | 意義 | 範例輸出 |
|---|---|---|
y | 年 (1~2 碼) | 23 |
yy | 年 (2 碼補 0) | 23 |
yyy | 年 (最少 3 碼) | 2023 |
yyyy | 年 (4 碼補 0) | 2023 |
M | 月 (1~2 碼) | 10 |
MM | 月 (2 碼補 0) | 10 |
MMM | 月縮寫 | Oct / 10月 |
MMMM | 月全名 | October / 十月 |
d | 日 (1~2 碼) | 31 |
dd | 日 (2 碼補 0) | 31 |
ddd | 星期縮寫 | Tue / 週二 |
dddd | 星期全名 | Tuesday / 星期二 |
h | 12小時制 (1~2 碼) | 2 |
hh | 12小時制 (2 碼補 0) | 02 |
H | 24小時制 (1~2 碼) | 14 |
HH | 24小時制 (2 碼補 0) | 14 |
m | 分 (1~2 碼) | 30 |
mm | 分 (2 碼補 0) | 30 |
s | 秒 (1~2 碼) | 15 |
ss | 秒 (2 碼補 0) | 15 |
f~fffffff | 秒小數部 (1~7 位) | .1 / .12 / .1234567 |
F~FFFFFFF | 秒小數部 (尾端 0 不顯示) | .1 / .12 / (無輸出若為 0) |
t | AM/PM 首字元 | P / 午 |
tt | AM/PM 完整 | PM / 下午 |
z | 時區偏移小時 (無補 0) | +8 |
zz | 時區偏移小時 (補 0) | +08 |
zzz | 時區偏移 時:分 | +08:00 |
: | 時間分隔符 (依文化特性) | : |
/ | 日期分隔符 (依文化特性) | / |
'text' 或 "text" | 常值字串 | Year: 2023 |
% | 單一字元格式前綴 | %y 等同 y |
\ | 跳脫字元 | \y 輸出 "y" |
var dt = new DateTime(2023, 10, 31, 14, 30, 15, 123);
dt.ToString("yyyyMMddHHmmss"); // 20231031143015 (檔名/Log 常用)
dt.ToString("yyyy-MM-dd HH:mm:ss"); // 2023-10-31 14:30:15 (資料庫/顯示)
dt.ToString("yyyy/MM/dd HH:mm:ss.fff"); // 2023/10/31 14:30:15.123 (高精度)
dt.ToString("yyyy年MM月dd日 HH:mm"); // 2023年10月31日 14:30 (中文報表)
dt.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'", CultureInfo.InvariantCulture); // RFC1123 手刻
| 成員 | 回傳型別 | 說明 | 範例 |
|---|---|---|---|
Now | DateTime | 本地目前時間 | 2023-10-31 14:30:15 |
UtcNow | DateTime | UTC 目前時間 | 2023-10-31 06:30:15 |
Today | DateTime | 本地今天 00:00:00 | 2023-10-31 00:00:00 |
Date | DateTime | 日期部分 (時間歸零) | 2023-10-31 00:00:00 |
Year/Month/Day | int | 年/月/日 | 2023, 10, 31 |
Hour/Minute/Second | int | 時/分/秒 | 14, 30, 15 |
Millisecond | int | 毫秒 (0~999) | 123 |
Ticks | long | 100ns 刻度 (從 0001/1/1) | 638357226151230000 |
DayOfWeek | DayOfWeek | 星期列舉 | Tuesday |
DayOfYear | int | 今年第幾天 | 304 |
TimeOfDay | TimeSpan | 時間部分 | 14:30:15.1230000 |
Kind | DateTimeKind | Unspecified/Utc/Local | Local |
AddDays(1.5) | DateTime | 加減天數 (可小數) | |
AddHours/Minutes/Seconds/Milliseconds/Ticks | DateTime | 加減時間單位 | |
AddMonths/Years | DateTime | 加減月/年 (處理月末) | |
ToLocalTime() | DateTime | UTC -> 本地 | |
ToUniversalTime() | DateTime | 本地 -> UTC | |
CompareTo(dt) | int | 比較大小 | -1/0/1 |
Equals(dt) | bool | 相等判斷 | true/false |
// 1. 嚴格格式解析 (推薦)
DateTime dt;
bool ok = DateTime.TryParseExact(
input,
"yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture, // 固定文化特性,避免伺服器設定影響
DateTimeStyles.None,
out dt);
// 2. 多格式嘗試
string[] formats = { "yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd" };
ok = DateTime.TryParseExact(input, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);
// 3. 解析含時區字串 (ISO 8601 / RFC3339)
ok = DateTimeOffset.TryParseExact(input, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out DateTimeOffset dto);
// DateTimeOffset 保留時區資訊,比 DateTime 更安全
// 4. 避免直接用 DateTime.Parse(input) — 依賴 CurrentCulture,部署環境不同會出錯
Unspecified (預設)、Utc、Local。ToLocalTime() 僅對 Utc 生效;Unspecified 視同 Local 轉換,**極易產生 Bug**。DateTime.UtcNow 或 DateTimeOffset.UtcNow),顯示時再轉使用者時區。ToString("D") 等標準格式**受 Thread.CurrentThread.CurrentCulture 影響**。Log/儲存/傳輸**務必指定 CultureInfo.InvariantCulture**。DateOnly、TimeOnly (無時區、無日期/時間混淆)、TimeZoneInfo、TimeProvider (可測試時間)。
// 檔名安全
DateTime.Now.ToString("yyyyMMdd_HHmmss_ffff")
// 資料庫 DateTime 欄位
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture)
// ISO 8601 / JSON 標準
DateTime.UtcNow.ToString("O") // 往返格式
DateTimeOffset.UtcNow.ToString("O") // 含時區
// RFC1123 / HTTP Header
DateTime.UtcNow.ToString("r", CultureInfo.InvariantCulture)
// 中文顯示
DateTime.Now.ToString("yyyy年MM月dd日 HH:mm:ss", new CultureInfo("zh-TW"))
// 週幾
DateTime.Now.ToString("dddd", new CultureInfo("zh-TW")) // 星期二
掌握 DateTime 格式化三大核心:**標準格式速度快、自訂格式彈性大、文化特性/時區必須顯式指定**。養成「儲存用 UTC + InvariantCulture、顯示才套用使用者文化特性」的習慣,能消除 90% 的日期時間 Bug。