DateTime.UtcNow 应该有时区偏移吗?

Should DateTime.UtcNow Have a Timezone Offset?

这个(LINQPad 片段):

DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz").Dump();
DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz").Dump();

Returns:

2016-01-08T09:05:04-07:00 // Expected
2016-01-08T16:05:04-07:00 // Not what I expected

鉴于第二个结果是世界时,我预计它是 return 2016-01-08T16:05:04-00:00(时区偏移量为零)。

我是不是遗漏了什么或者这是一个错误?

我想结合 and 评论,如果他们允许的话,我会提出一些反对意见。让我们一步步来..

Should DateTime.UtcNow have a timezone offset?

无论 Kind 它有什么(本地、Utc 或未指定),DateTime 实例不会保留 any UTC 偏移值。期间.

首先,让我们看一下The "zzz" format specifier文档;

With DateTime values, the "zzz" custom format specifier represents the signed offset of the local operating system's time zone from UTC, measured in hours and minutes. It does not reflect the value of an instance's DateTime.Kind property. For this reason, the "zzz" format specifier is not recommended for use with DateTime values.

根据前两个粗体句子,LINQPad 生成的两个结果完全符合预期。您 也可以 在 Visual Studio 中获得相同的结果(当然需要日期和时间部分 )。

只需运行此代码为"Start Without Debugging" (Ctrl + F5)

Console.WriteLine(DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz"));
Console.WriteLine(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz"));

但是当你 运行 它作为 "Start Debugging" 和 (F5) 时呢?

在这种情况下有两个选项取决于您是否勾选了DateTimeInvalidLocalFormat in Managed Debugging Assistants。此部分位于 Debug 菜单中,然后单击 Exceptions

如果勾选了这个选项,你会得到一个例外,它说;

A UTC DateTime is being converted to text in a format that is only correct for local times. This can happen when calling DateTime.ToString using the 'z' format specifier, which will include a local time zone offset in the output. In that case, either use the 'Z' format specifier, which designates a UTC time, or use the 'o' format string, which is the recommended way to persist a DateTime in text.

如果不勾选此选项,您将不会收到任何消息,结果与 LINQPad 相同。

Given that the 2nd result is universal time, I expected it to return 2016-01-08T16:05:04-00:00 (timezone offset of zero).

正如我所解释的,zzz 格式说明符 not 的行为类似于 any DateTime 实例。

但是对于记录为 DateTimeOffset 的实例,它的行为有所不同;

With DateTimeOffset values, this format specifier represents the DateTimeOffset value's Offset from UTC in hours.

DateTimeOffset.Now and DateTimeOffset.UtcNow 完全符合您的期望,无论您是在 LINQPad 中 运行 还是 Visual Studio,因为它们被记录为;

现在

A DateTimeOffset object whose date and time is the current local time and whose offset is the local time zone's offset from Coordinated Universal Time (UTC).

UtcNow

An object whose date and time is the current Coordinated Universal Time (UTC) and whose offset is TimeSpan.Zero.

Console.WriteLine(DateTimeOffset.Now.ToString("yyyy-MM-ddTHH:mm:sszzz"));
Console.WriteLine(DateTimeOffset.UtcNow.ToString("yyyy-MM-ddTHH:mm:sszzz"));

会生成

2016-01-08T09:05:04-07:00
2016-01-08T16:05:04-00:00

Tl;dr 我认为这 不是 错误。 LINQPad 生成正确的结果 完全 它应该是什么。在 Visual Studio 中,如果 that 选项在调试模式下被勾选或未被勾选,你 可能会 得到一个异常。