標準格式字串 (單一字元)
| 格式 | 說明 | 範例 (en-US) | 範例 (zh-TW) |
| d | 短日期 | 6/15/2023 | 2023/6/15 |
| D | 長日期 | Thursday, June 15, 2023 | 2023年6月15日 |
| f | 完整日期短時間 | Thursday, June 15, 2023 3:30 PM | 2023年6月15日 下午 03:30 |
| F | 完整日期長時間 | Thursday, June 15, 2023 3:30:45 PM | 2023年6月15日 下午 03:30:45 |
| g | 一般日期短時間 | 6/15/2023 3:30 PM | 2023/6/15 下午 03:30 |
| G | 一般日期長時間 | 6/15/2023 3:30:45 PM | 2023/6/15 下午 03:30:45 |
| M/m | 月日 | June 15 | 6月15日 |
| O/o | ISO 8601 往返格式 | 2023-06-15T15:30:45.1234567 | (同) |
| R/r | RFC 1123 | Thu, 15 Jun 2023 15:30:45 GMT | (同) |
| s | 可排序日期時間 (ISO 8601 無時區) | 2023-06-15T15:30:45 | (同) |
| t | 短時間 | 3:30 PM | 下午 03:30 |
| T | 長時間 | 3:30:45 PM | 下午 03:30:45 |
| u | 通用可排序 (UTC) | 2023-06-15 15:30:45Z | (同) |
| U | 完整日期長時間 (UTC) | Thursday, June 15, 2023 11:30:45 PM | 2023年6月15日 上午 11:30:45 |
| Y/y | 年月 | June 2023 | 2023年6月 |
自訂格式字元 (可組合)
| 字元 | 意義 | 範例 |
| y | 年 (1-2 碼) | 23 |
| yy | 年 (2 碼) | 23 |
| yyyy | 年 (4 碼) | 2023 |
| M | 月 (1-2 碼) | 6 |
| MM | 月 (2 碼) | 06 |
| MMM | 月縮寫 | Jun / 6月 |
| MMMM | 月全名 | June / 六月 |
| d | 日 (1-2 碼) | 15 |
| dd | 日 (2 碼) | 15 |
| ddd | 星期縮寫 | Thu / 週四 |
| dddd | 星期全名 | Thursday / 星期四 |
| h | 12小時制 (1-2 碼) | 3 |
| hh | 12小時制 (2 碼) | 03 |
| H | 24小時制 (1-2 碼) | 15 |
| HH | 24小時制 (2 碼) | 15 |
| m | 分 (1-2 碼) | 30 |
| mm | 分 (2 碼) | 30 |
| s | 秒 (1-2 碼) | 45 |
| ss | 秒 (2 碼) | 45 |
| f..fffffff | 秒小數位 (1-7 碼) | .1 / .12 / .1234567 |
| t | AM/PM 首字元 | P / 午 |
| tt | AM/PM 全稱 | PM / 下午 |
| z | 時區時差 (小時) | +8 |
| zz | 時區時差 (小時 2碼) | +08 |
| zzz | 時區時差 (時:分) | +08:00 |
| : | 時間分隔符 (依文化) | : |
| / | 日期分隔符 (依文化) | / |
| 'text' | 常值字串 | 'Year: 'yyyy → Year: 2023 |
| \c | 跳脫單一字元 | \: → : |
文化特性控制
var dt = new DateTime(2023, 6, 15, 15, 30, 45);
var tw = new CultureInfo("zh-TW");
var us = new CultureInfo("en-US");
var jp = new CultureInfo("ja-JP");
Console.WriteLine(dt.ToString("D", tw)); // 2023年6月15日
Console.WriteLine(dt.ToString("D", us)); // Thursday, June 15, 2023
Console.WriteLine(dt.ToString("yyyy年M月d日", CultureInfo.InvariantCulture)); // 固定格式,不受文化影響
高效能格式化
| 場景 | 建議做法 |
| 高頻呼叫 (每秒 > 10 萬) | 避免 `ToString` 配置字串,改用 `StringBuilder` + `AppendFormat` 或手寫格式化 |
| 固定格式 (如 log 時間戳) | 預先建立 `DateTimeFormatInfo` 快取,或用 `Utf8Formatter` (NET Core 2.1+) 直接寫入 `Span` |
| 資料庫參數 | 勿格式化字串,直接傳 `DateTime` 參數化查詢 |
| JSON 序列化 | 使用 `JsonSerializerOptions` 設定 `DateTimeFormat = "O"` (ISO 8601 往返) |
常見陷阱
- yyyy vs YYYY:`YYYY` 是週年 (ISO 8601 週曆),跨年週會導致年份錯誤,**永遠用 `yyyy`**。
- mm vs MM:`mm` 是分鐘,`MM` 是月份。**嚴格區分大小寫**。
- 單一字元自訂格式:`dt.ToString("d")` 是標準短日期,**自訂單字元需 `%d` 或 `"d "`** (加空白)。
- 時區轉換:`DateTime.Kind` (Unspecified/Utc/Local) 影響 `ToString("O")` 輸出 Z/+00:00,儲存/傳輸建議統一 UTC。
總結
掌握 **標準格式 (單字元)** 、**自訂格式字元 (大小寫敏感)** 、**文化特性 (IFormatProvider)** 三大支柱,並避開 `yyyy/YYYY`、`mm/MM`、時區、`Kind` 等經典坑洞。高效能場景改用 `Utf8Formatter` 或手寫格式化。統一儲存 UTC、顯示時再按文化轉換,是國際化系統的最佳實務。
- 上一篇文章: C# 敏感資訊遮罩工具:手機號、身分證、信用卡號通用實作
- 下一篇文章: C# XML 動態遞歸綁定 TreeView 完整實作
Copyright ©
程式碼之家 All Rights Reserved