【问题标题】:Why is DateTime.Now.Subtract(DateTime.UtcNow) not (close to) zero?为什么 DateTime.Now.Subtract(DateTime.UtcNow) 不(接近)零?
【发布时间】:2012-08-21 19:52:24
【问题描述】:

如果我尝试:

DateTime.Now.Subtract(DateTime.UtcNow)

我希望结果非常接近于零。但这不是,而是时区差异,在我的情况下是-4小时。有一个 .Kind - DateTime 知道时区不同。为什么它不为我跟踪这个?有没有正确使用 Kind 的 Subtract 风格?

(作为参考,可以在https://stackoverflow.com/a/3229429/237091 看到每个输出的一个很好的概要)

【问题讨论】:

  • DateTime.Now 返回当前系统DateTimeDateTime.UtcNow 还将时区转换应用于UTCDateTime 没有时区的内部表示。也许你需要DateTimeOffset
  • 如果你在冰岛雷克雅未克运行它,你会得到零
  • 欢迎来到DateTime 的世界。 “种类”被忽略。在 .NET 1 中它甚至不存在,现在让事情变得合乎逻辑已经太晚了。
  • @exacerbatedexpert:不,对局部值进行各种算术运算是完全合理的。在许多情况下,我认为这比在 UTC 中进行更明智这里显示的算术没有意义,但其他算术当然可以。

标签: c# .net


【解决方案1】:

诶? Kind 属性不会改变日期数学。它仅由时区方法使用。

你得到的结果正是我期望你得到的。不知道我理解你为什么期待零。

【讨论】:

  • 它会有意义改变日期数学 - 如果只是抛出一个异常。从根本上说,IMO 将 UTC 日期/时间与本地日期/时间进行比较是没有意义的 - 或者至少您想指定您尝试执行的算术类型。
  • @JonSkeet:请不要再有例外!我们有足够的时间尝试处理所有可能的异常。是的,我想如果Kind 得到更强有力的实施,我会明白它的意义。
  • @JonathanWood:你不应该试图处理它——你应该修复你的代码,这样它就不会发生! (这将是一个ArgumentException - 这几乎总是意味着“你的代码被破坏了”。)你应该只处理由于外部情况等引起的异常。
  • @JonSkeet:不幸的是,我们不是完美的程序员。而且我们有时没有意识到,例如,一个值实际上可能为空的情况。对我们来说,这就是真实的世界。我们付出了巨大的努力来确保处理所有异常情况。
  • @JonathanWood:我们并不完美,这正是异常如此好的原因。因为如果我犯了一个逻辑错误,我几乎总是宁愿中止我正在做的事情,而不是继续使用错误的值。如果您不知道某事是否为空,请检查它。如果您知道它应该为空,请验证它。
【解决方案2】:

有一个 .Kind - DateTime 知道时区不同。为什么它不为我跟踪这个?

因为DateTime is fundamentally broken (and there's more...)。如果您尝试从另一种值中减去一种值,IMO 应该会抱怨。但是不,它只是在每个值中使用未解释的日期/时间。不幸的是,实际上很少有操作会注意到Kind。 (如果你使用TimeZoneInfo,那些操作确实会注意到它。)

Kind 被入侵 .NET 2.0;在此之前 DateTime 值甚至不知道它是什么类型 - 如果你使用过:

dt = dt.ToLocalTime().ToLocalTime().ToLocalTime();

它将多次应用相同的偏移更改。 BCL 团队在二进制表示中找到了几个备用位,并将其用于Kind

基本上,我能感觉到你的痛苦。如果这样的操作引发异常,我个人更喜欢它 - 从本地 DateTime 中减去 UTC DateTime 或反之亦然没有意义,IMO。

作为一个完全有偏见的插件,您可以使用Noda Time,它将InstantLocalDateLocalTimeLocalDateTimeOffsetDateTimeZonedDateTime 的想法分开,并且不会让您执行无意义的算术。我们的目标是提供比 BCL 更健全的 API。当然,这并不一定意味着我们已经成功了:)

【讨论】:

    【解决方案3】:

    每个DateTime 对象代表一个本地时间(而不是UTC 时间加上时区偏移)。即使Kind 属性等于UTC,它也只是将本地时间存储在零时区。如果不是当地时间,则没有理由使用 UtcNow 属性。

    DateTime 甚至不存储时区。如果Kind 等于UTC,那么至少您知道它的时区为零,但如果Kind 是本地的或未指定的,则无法知道时区(Kind 属性默认等于Unspecified)。

    因此,Subtract 方法无法将时区纳入其计算中,因为时区未知。

    【讨论】:

    • 不,请查看DateTime.Kind 的文档。
    • @JonSkeet,我了解Kind 属性。我说了什么不准确的?
    • “每个 DateTime 对象代表一个本地时间” - 对于 DateTime.Kind of Utc,表示的日期/时间是 UTC,而不是本地时间。虽然我怀疑我知道你的意思,但你至少用一种非常混乱的方式表达了它。
    • 有点。不理想,但DateTime :( Subtract 当然可以UTC - Local 的情况下考虑时区,尽管这可能会更糟。正如我所说在其他地方,抛出异常会更好 IMO。
    猜你喜欢
    • 2018-09-19
    • 1970-01-01
    • 2020-09-12
    • 2011-05-03
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    相关资源
    最近更新 更多