为什么 [datetime] 正确转换此 UTC 时间以及如何使用 ParseExact 复制它

Why is [datetime] converting this UTC time correctly and how can I replicate that with ParseExact

我觉得自己搞不定这个问题很傻。

我有来自 CarbonBlack 的日期 API 例如2022-02-15-172040 是 UTC

如果我删除字符串的秒部分,[datetime] 类型转换工作正常

PS M:\Scripts> [datetime]"2022-02-15-1720"   
Tuesday, February 15, 2022 12:20:00 PM

我不明白它是如何“知道”那是一个 UTC 字符串。这当然是正确的,但我预计时间部分为 5:20pm。我想要日期的秒数,所以我去精确解析,因为据我所知这不匹配任何格式字符串

PS M:\Scripts> [datetime]::ParseExact("2022-02-15-172040", "yyyy-MM-dd-HHmmss" ,[Globalization.CultureInfo]::CurrentUICulture)
Tuesday, February 15, 2022 5:20:40 PM

这是我预期的时间,但时间不正确。

为什么 [datetime] 在我不希望它工作的时候工作,我需要对字符串或静态方法调用做些什么才能将其视为 UTC 字符串且操作最少?

这是因为

([datetime]"2022-02-15-1720").Kind

产生“本地”,而

([datetime]::ParseExact("2022-02-15-172040", "yyyy-MM-dd-HHmmss",[CultureInfo]::InvariantCulture)).Kind

returns '未指定'

如果您希望结果将字符串处理为 Local 时间,然后结果应为 UTC,请使用:

([datetime]::ParseExact("2022-02-15-172040", "yyyy-MM-dd-HHmmss",[CultureInfo]::InvariantCulture, 'AssumeLocal')).ToUniversalTime()

$date = [datetime]::ParseExact("2022-02-15-172040", "yyyy-MM-dd-HHmmss",[CultureInfo]::InvariantCulture)
[datetime]::SpecifyKind($date, 'Local').ToUniversalTime()

反之,如果您认为字符串中的日期表示 UTC(世界标准时间),并且您希望结果在 当地时间,你需要这样做:

[datetime]::ParseExact("2022-04-29-185121", "yyyy-MM-dd-HHmmss",[CultureInfo]::InvariantCulture, 'AssumeUniversal')

此处,ParseExact() 将字符串视为 UTC 并输出 转换为本地时间的日期
(.Kind --> 'Local'),这是与

完全相同的输出
[datetime]"2022-04-29-1851"

会给出:也在这里,.Kind --> 'Local'`

如果您希望结果日期为 UTC,则需要使用 .ToUniversalTime()

将其再次转换回来

棘手的部分是使用 ParseExact() 没有 第三个参数('AssumeLocal' 或 'AssumeUniversal')时解析没有 表明它是本地或 UTC,就像这里的示例字符串一样,总是返回一个日期时间对象,其 .Kind 属性 设置为 Unspecified.

感谢 的评论, 在 PowerShell (Core) 7+ 中,示例中的字符串不再被识别,并且应该有一个时区指示,如“2022-02-15 17:20Z”。 ('Z' --> 祖鲁 (UTC) 时间)

如果你给它第三个参数,告诉它应该使用哪个时区('AssumeLocal' 或 'AssumeUniversal'),生成的日期时间对象将 始终将其 .Kind 属性 设置为 Local 如果您将 AssumeUniversal 作为参数,结果将转换为本地时间。