为何PowerShell中[datetime]类型转换可正确识别UTC时间?如何通过ParseExact实现同效转换
这问题确实有点绕,我来帮你理清楚背后的逻辑,再给你最直接的解决方案。
为什么直接[datetime]转换能“自动识别”UTC?
当你直接用[datetime]"2022-02-15-1720"做强制转换时,PowerShell底层其实调用的是[datetime]::Parse()方法。这个方法内置了一套格式识别逻辑,对于yyyy-MM-dd-HHmm这种看起来像标准化UTC日志格式的字符串,它会默认把它当作UTC时间来解析。
解析后得到的DateTime对象的Kind属性会被标记为UTC,而PowerShell在显示这个对象时,会自动转换成你的本地时区(比如你在UTC-5时区,UTC的17:20就会显示为本地的12:20 PM),这就是你觉得“结果正确”的原因——它确实识别了UTC,只是做了时区转换显示。
为什么ParseExact默认得到“错误”结果?
ParseExact是严格匹配格式的方法,它的默认行为是:如果格式字符串里没有时区信息(比如你的yyyy-MM-dd-HHmmss),它会把字符串当作本地时间来解析。所以你得到的17:20:40 PM其实是你的本地时间,而不是UTC时间,这自然不符合你的需求。
最小改动:让ParseExact把字符串当作UTC处理
只需要给ParseExact添加第四个参数,指定DateTimeStyles.AssumeUniversal,同时把文化信息换成InvariantCulture(这是最佳实践,避免区域设置影响解析):
[datetime]::ParseExact("2022-02-15-172040", "yyyy-MM-dd-HHmmss", [Globalization.CultureInfo]::InvariantCulture, [Globalization.DateTimeStyles]::AssumeUniversal)
这个调用会告诉解析器:“这个字符串是UTC时间”,解析出的DateTime对象Kind会被标记为UTC,显示时同样会转换成你的本地时区(和直接转换的结果一致:Tuesday, February 15, 2022 12:20:40 PM),而且内部存储的是正确的UTC时间,后续处理不会出错。
如果你想直接查看UTC时间的原始值,可以这样输出:
$utcDt = [datetime]::ParseExact("2022-02-15-172040", "yyyy-MM-dd-HHmmss", [Globalization.CultureInfo]::InvariantCulture, [Globalization.DateTimeStyles]::AssumeUniversal) $utcDt.ToString("yyyy-MM-dd HH:mm:ss UTC") # 输出:2022-02-15 17:20:40 UTC
内容的提问来源于stack exchange,提问作者Matt

