datetime.tostring() 是最轻量的日期格式化方式,应优先使用标准格式符(如"s"用于数据库、"o"用于跨服务),注意文化设置、大小写敏感及分隔符替换问题。

直接用 DateTime.ToString() 就行,别绕弯——它是最轻量、最常用、也最容易出错的入口。
标准格式符(如 "d"、"G"、"o")怎么选
标准格式符是单字母或单字母加文化参数,安全、简洁、不依赖本地设置(只要你不传错 culture)。它们背后对应系统预设的 DateTimeFormatInfo 规则,比如:
-
"d"→ 短日期:中文环境是"2026/4/27",英文是"4/27/2026" -
"G"→ 常规日期+长时间:"2026/4/27 23:01:05",适合日志但分隔符不固定 -
"s"→ 可排序的 ISO 局部时间:"2026-04-27T23:01:05",无时区、无毫秒、无文化干扰,推荐用于数据库存储或内部接口 -
"o"→ 往返格式(注意是大写 O):"2026-04-27T23:01:05.1234567+08:00",带毫秒和时区偏移,适合跨服务传输,但要求dt.Kind != DateTimeKind.Unspecified,否则会按本地时区补偏移,容易误判
别用 "u" 做通用时间输出——它强制转 UTC 并砍掉毫秒、去掉冒号、固定结尾为 Z,看着像 ISO 实际不是,且不可逆。
自定义格式字符串里哪些字母必须小心大小写
大小写敏感是硬规则,"MM" 和 "mm" 完全不同:"MM" 是月,"mm" 是分;"HH" 是 24 小时制小时,"hh" 是 12 小时制。常见踩坑点:
- 写成
"yyyy-mm-dd"→ 实际输出是年-分-日(因为mm被当成分) - 写成
"yyyy-M-d"→ 在某些文化下(如阿拉伯语)可能崩,建议统一用"yyyy-MM-dd"补零 -
"y"单字母年份不推荐 —— 在部分文化中行为未定义,甚至抛异常;坚持用"yy"或"yyyy" - 要显示“上午/下午”,别依赖
"tt"(它输出英文 AM/PM),中文场景直接写死:"yyyy年MM月dd日 HH:mm:ss 上午"或用CultureInfo("zh-CN")
为什么 DateTime.Now.ToString("yyyy/MM/dd") 在德语系统里变成 2026.04.27
因为 / 是“日期分隔符占位符”,不是字面斜杠。它会被当前线程的 CultureInfo 替换为该文化默认的分隔符(德语用点,法语用空格)。真正想固定输出 2026/04/27,必须显式指定不变量:
- ✅ 正确:
DateTime.Now.ToString("yyyy'/'MM'/'dd", CultureInfo.InvariantCulture) - ✅ 更简洁:
DateTime.Now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)(连字符在所有文化中都保持原义) - ❌ 错误:
DateTime.Now.ToString("yyyy/MM/dd")—— 不可控
同理,"HH:mm:ss" 中的 : 也会被替换成当地时间分隔符(如阿拉伯语用 ٠),需用 ':' 包裹或改用 InvariantCulture。
String.Format 和 $ 插值里怎么写格式化
它们底层还是调用 ToString(string),语法更紧凑,但规则完全一致:
string.Format("{0:yyyy-MM-dd HH:mm:ss}", dt)$"{dt:yyyy-MM-dd HH:mm:ss}"
注意两点:
- 插值中不能用双引号包裹格式串(如
$"{dt:"yyyy-MM-dd"}"是语法错误),必须单引号或直接写 - 如果格式串含花括号(如要输出
{2026}),得写成$"{{dt:yyyy}}"—— 两个大括号才表示一个字面大括号
真正麻烦的从来不是“怎么写出来”,而是“为什么在测试机上对、上线就错”——根源几乎都在文化设置没锁死、时区 Kind 没校验、或者把分当月这种低级大小写混淆上。











