【问题标题】:Should DateTime.UtcNow Have a Timezone Offset?DateTime.UtcNow 应该有时区偏移吗?
【发布时间】:2016-04-13 09:35:04
【问题描述】:

这个(LINQPad sn-p):

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

返回:

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

鉴于第二个结果是世界时,我希望它返回2016-01-08T16:05:04-00:00(时区偏移为零)。

是我遗漏了什么还是这是一个错误?

【问题讨论】:

  • 如果您在控制台应用程序中尝试这样做,它会引发异常,因为 UtcNow 无法使用指定的格式,因为它没有区域......所以该格式对 UtcNow 无效,并且有一些忽略这一点的 LINQPad 中的错误
  • 如果你使用DateTimeOffset而不是DateTime,那就是正确的。
  • 谢谢!在这两个 cmets 之间,我有一个解释和一个解决方法,如果你想把它放在一个中,我很乐意接受任何一个作为答案。
  • @Gusman 我认为这是 LINQPad 中的错误。请看我的回答。

标签: c# .net datetime utc linqpad


【解决方案1】:

我想将Gusman'sEvan's cmets 结合起来,如果他们允许的话,我会提出一些反对他们的论据。让我们一步一步来..

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

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

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

对于 DateTime 值,“zzz”自定义格式说明符表示 本地操作系统时区与 UTC 的带符号偏移量, 以小时和分钟为单位。 它不反映一个人的价值 实例的 DateTime.Kind 属性。因此,“zzz”格式 说明符不推荐用于 DateTime 值。

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

只需将此代码运行为“不调试就启动”(Ctrl + F5)

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

但是,当您使用 (F5) 将其作为“开始调试”运行时呢?

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

如果勾选了这个选项,你会得到一个异常,它会说:

A UTC DateTime 被转换为文本格式,仅 正确的当地时间。调用时可能会发生这种情况 DateTime.ToString 使用 'z' 格式说明符,其中将包括 输出中的本地时区偏移量。在这种情况下,要么使用'Z' 格式说明符,指定 UTC 时间,或使用 'o' 格式 字符串,这是在文本中保存 DateTime 的推荐方式。

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

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

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

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

对于DateTimeOffset 值,此格式说明符表示 DateTimeOffset 值的 Offset 以小时为单位,UTC 时间。

并且DateTimeOffset.NowDateTimeOffset.UtcNow 完全符合您的期望,无论您在 LINQPad 或 Visual Studio 中运行,因为它们被记录为;

现在

一个 DateTimeOffset 对象,其日期和时间是当前本地时间 并且其偏移量是本地时区相对于 Coordinated 的偏移量 世界标准时间 (UTC)

UtcNow

一个对象,其日期和时间是当前的 Coordinated Universal 时间 (UTC) 和 其偏移量是 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 选项被勾选或未处于调试模式,您可能会遇到异常。

【讨论】:

    猜你喜欢
    • 2016-09-05
    • 1970-01-01
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    • 2017-11-07
    相关资源
    最近更新 更多