datetime.adddays() 不修改原实例,只返回新 datetime 实例;错误写法如 dt.adddays(1) 会丢弃返回值,正确应写为 dt = dt.adddays(1),链式调用如 adddays(1).addhours(2) 是安全的。

DateTime 本身不可变,所有“修改”操作都返回新实例——这是绝大多数误用的根源。
为什么 DateTime.AddDays() 没生效?
因为 DateTime 是值类型且不可变,AddDays() 等方法从不修改原变量,只返回新值。
- 错误写法:
dt.AddDays(1);—— 返回值被丢弃,dt完全没变 - 正确写法:
dt = dt.AddDays(1); - 链式调用安全:
var tomorrow = DateTime.Now.AddDays(1).AddHours(2);
常见于循环中忘记赋值,结果反复在原始时间上加,而非累加。
DateTime.Parse() 和 DateTime.TryParse() 怎么选?
取决于输入是否可信。生产环境几乎 always 用 TryParse()。
-
Parse()遇到非法字符串直接抛FormatException,容易崩 -
TryParse()返回bool,成功时通过out参数输出结果,可控 - 带格式解析用
TryParseExact(),例如:DateTime.TryParseExact("20240520", "yyyyMMdd", null, DateTimeStyles.None, out var d)
注意:null 作为 IFormatProvider 参数会使用当前线程文化,若需固定行为(如服务端),显式传 CultureInfo.InvariantCulture。
本地时间、UTC 时间、时区转换怎么不出错?
混淆 Kind 属性是时区相关 bug 的最大来源。
-
DateTime.Now.Kind == DateTimeKind.Local,DateTime.UtcNow.Kind == DateTimeKind.Utc - 跨时区计算前,务必确认
Kind:用SpecifyKind()显式标注,或用ToUniversalTime()/ToLocalTime()转换 - 避免直接比较
Local和Utc实例——它们语义不同,即使值相同也可能因Kind不同导致逻辑错误 - 需要真正时区支持(如夏令时)?别硬扛,改用
DateTimeOffset或TimeZoneInfo
DateTimeOffset 才是带偏移量的“真实时间戳”,DateTime 只是日历+时钟读数,没有隐含时区含义。
性能敏感场景下,哪些操作要警惕?
多数 DateTime 操作很快,但以下情况有隐性开销:
-
ToString()格式化(尤其带文化信息时):缓存常用格式字符串,避免每次拼接 -
DateTime.Now每次调用都触发系统调用,高频循环中考虑一次取值复用 -
DateTime.Parse()内部做大量文化感知解析,比TryParseExact()慢数倍,且行为不稳定 - 频繁创建
DateTime实例本身无压力,但若搭配字符串操作(如日志拼接),注意ToString()分配
最常被忽略的是:把 DateTime 当“时间点”用,却没管 Kind;或者当成可变对象,忘了赋值。










