DateTime.Now 与 DateTime.UtcNow

Posted

技术标签:

【中文标题】DateTime.Now 与 DateTime.UtcNow【英文标题】:DateTime.Now vs. DateTime.UtcNow 【发布时间】:2010-09-08 21:29:38 【问题描述】:

我一直想知道这两个属性的工作原理到底是什么。我知道第二个是通用的,基本上不涉及时区,但是有人可以详细解释一下它们是如何工作的以及在什么情况下应该使用哪个?

【问题讨论】:

可能为时已晚,但我想指出这个博客:blog.angeloflogic.com/2013/10/… 小标杆rextester.com/QRDR82396 【参考方案1】:

DateTime.UtcNow 告诉您日期和时间,就像协调世界时一样,也称为格林威治标准时区 - 基本上就像您在英国伦敦时一样,但不是在夏季。 DateTime.Now 给出日期和时间,就像您当前区域设置中的某个人看到的那样。

我建议您在向人显示日期时使用DateTime.Now - 这样他们就会对他们看到的价值感到满意 - 他们可以轻松地将其与他们在手表上看到的内容进行比较或钟。当您想要存储日期或将它们用于以后的计算时,请使用 DateTime.UtcNow(在客户端-服务器模型中),您的计算不会被来自服务器或彼此不同时区的客户端混淆。

【讨论】:

一个很好的观点——当在数据库或文件中存储日期时,一定要以UTC格式存储它们! 您必须注意,当您想在数据库中以 UTC 格式存储日期时,您必须确保数据库不会将自己的时区添加到未提供明确时区的日期中。请注意,当被要求时,DateTime 将始终使用当前时区。 @JoshYates1980 是的,您只需执行 DateTime.UtcNow.AddYears(1) 使用NodaTime - 它会迫使你以更有用的方式思考时间并避免此类问题 我敢肯定,当您说“我建议使用 DateTime.Now”时,那是 2008 年,云并不存在。您不认为 UTC.Now 是当今的正确选择,因为所有内容都部署在具有国际受众的地理分布式云上吗?【参考方案2】:

这真的很简单,所以我认为这取决于你的观众是什么以及他们住在哪里。

如果您不使用 Utc,您必须知道您要向其显示日期和时间的人的时区 - 否则您会告诉他们下午 3 点在系统或服务器中发生的事情时间,真正发生在他们碰巧住的下午 5 点。

我们使用DateTime.UtcNow 是因为我们拥有全球网络受众,而且我不想唠叨每个用户填写一份表明他们所在时区的表格。

我们还会显示相对时间(2 小时前、1 天前等),直到帖子的时间长到足以“相同”,无论您住在地球上的哪个地方。

【讨论】:

我还想知道,存储 DateTime.UtcNow 也仅在完成 ​​2 个日期的计算以获得正确的时间时才需要。当我只需要显示 RegisterAt Date 时,Datetime.Now 就足够了。【参考方案3】:

还要注意性能差异; DateTime.UtcNowDateTime.Now 快大约 30 倍,因为在内部 DateTime.Now 正在做很多时区调整(您可以使用 Reflector 轻松验证这一点)。

所以不要使用DateTime.Now 进行相对时间测量。

【讨论】:

这让我经历了一段痛苦的旅程,只知道 UtcNow 具有更好的性能,只需将您的日期保存在 mysql 中并假设它是 utc 并将日期相关显示与 UtcNow 进行比较简化了这个全球时区问题 在我的电脑上只有3 倍快。我创建了一个具有一百万次迭代的循环。使用 datetime.now 需要 200 毫秒。使用 datetime.utcnow 需要 60 毫秒。【参考方案4】:

在 .NET 中要理解的一个主要概念是,无论您在哪个时区,now 都是now 遍布全球。因此,如果您使用DateTime.NowDateTime.UtcNow -- 分配是相同的。* 您的 DateTime 对象知道您所在的时区,并且无论分配如何都会考虑到这一点。

DateTime.UtcNow 在计算跨夏令时边界的日期时非常有用。即在参与夏令时的地方,有时从中午到次日中午有25小时,有时从中午到次日中午有23小时。如果您想正确确定从时间 A 到时间 B 的小时数,您需要先将每个时间转换为它们的 UTC 等效值,然后再计算 TimeSpan

blog post i wrote 对此进行了介绍,进一步解释了TimeSpan,并包含指向有关该主题的更广泛的 MS 文章的链接。

*澄清:任一分配都将存储当前时间。如果您要通过DateTime.Now() 加载两个变量,另一个通过DateTime.UtcNow() 加载两个变量,则两者之间的TimeSpan 差异将是毫秒,而不是小时,假设您在距离格林威治标准时间数小时的时区。如下所述,打印出它们的String 值将显示不同的字符串。

【讨论】:

关于“使用 DateTime.Now 或 DateTime.UtcNow 加载变量——赋值相同”:这可能需要澄清吗?当我坐在 EDT 时区 (UTC -4) 中时,我分别将两个变量分配给 DateTime.UtcNow 和 DateTime.Now,然后使用 ToString() 打印它们的值。显示的值相隔 4 小时 - 不“相同”。 @JonSchneider,我相信你是对的。陈述:“分配是相同的”是不正确的。 ToString() 可能不是最好的测试方法,因为它可以以不同的方式显示相等的日期(就像 Java 那样)。比较函数是一种更好的测试,并且表明它们确实不相等。 澄清我的“相同”声明:通过 DateTime.Now 加载一个变量,用 DateTime.UtcNow 加载另一个变量,然后打印 TimeSpan 差异。假设您距离格林威治标准时间数小时,差异将是毫秒而不是小时。【参考方案5】:

这是个好问题。我正在恢复它以更详细地说明 .Net 在不同 Kind 值下的行为方式。正如@Jan Zich 指出的那样,它实际上是一个非常重要的属性,并且根据您使用的是Now 还是UtcNow 而设置不同。

日期在内部存储为Ticks(与@Carl Camera 的回答相反),具体取决于您使用的是Now 还是UtcNow

DateTime.UtcNow 的行为类似于其他语言。它将 Ticks 设置为基于 GMT 的值。它还将Kind 设置为Utc

DateTime.NowTicks 值更改为如果它是您在 GMT 时区的一天中的时间。它还将Kind 设置为Local

如果您落后 6 小时 (GMT-6),您将获得 6 小时前的 GMT 时间。 .Net 实际上忽略了Kind 并将这个时间视为 6 小时前,即使它应该是“现在”。如果您创建一个 DateTime 实例,然后更改您的时区并尝试使用它,这会更糟。

具有不同 'Kind' 值的 DateTime 实例不兼容。

让我们看一些代码...

    DateTime utc = DateTime.UtcNow;
    DateTime now = DateTime.Now;
    Debug.Log (utc + " " + utc.Kind);  // 05/20/2015 17:19:27 Utc
    Debug.Log (now + " " + now.Kind);  // 05/20/2015 10:19:27 Local

    Debug.Log (utc.Ticks);  // 635677391678617830
    Debug.Log (now.Ticks);  // 635677139678617840

    now = now.AddHours(1);
    TimeSpan diff = utc - now;
    Debug.Log (diff);  // 05:59:59.9999990

    Debug.Log (utc <  now);  // false
    Debug.Log (utc == now);  // false
    Debug.Log (utc >  now);  // true

    Debug.Log (utc.ToUniversalTime() <  now.ToUniversalTime());  // true
    Debug.Log (utc.ToUniversalTime() == now.ToUniversalTime());  // false
    Debug.Log (utc.ToUniversalTime() >  now.ToUniversalTime());  // false
    Debug.Log (utc.ToUniversalTime() -  now.ToUniversalTime());  // -01:00:00.0000010

正如您在此处看到的,比较和数学函数不会自动转换为兼容时间。 Timespan 应该是将近一个小时,但实际上是将近 6 个。“utc

您还可以看到“变通办法”,即在 Kind 不同的任何地方简单地转换为世界时间。

我对该问题的直接回答与接受的答案关于何时使用每个问题的建议一致。您应该始终尝试使用具有 Kind=UtcDateTime 对象,除非在 i/o(显示和解析)期间。这意味着您应该几乎总是使用DateTime.UtcNow,除非您创建对象只是为了显示它,然后立即丢弃它。

【讨论】:

【参考方案6】:

DateTime 不知道时区是什么。它始终假定您在当地时间。 UtcNow 仅表示“从时间中减去我的时区”。

如果您想使用可识别时区的日期,请使用 DateTimeOffset,它表示带有时区的日期/时间。我必须以艰难的方式学习这一点。

【讨论】:

完全准确地说(并避免人们出于性能原因使用 Now 而不是 UtcNow),反之亦然:Now 将时区添加到 UtcNow,实际上慢了一个数量级。【参考方案7】:

这个问题的“简单”答案是:

DateTime.Now 返回一个 DateTime 值,表示当前的系统时间(在系统运行的任何时区)。 DateTime.Kind 属性将为 DateTimeKind.Local

DateTime.UtcNow 返回一个 DateTime 值,表示当前的通用协调时间(又名 UTC),无论系统的时区如何,该值都是相同的。 DateTime.Kind 属性将为 DateTimeKind.Utc

【讨论】:

【参考方案8】:

只是对上述几点的补充:DateTime 结构还包含一个鲜为人知的字段Kind(至少,我很长一段时间都不知道它)。它基本上只是一个指示时间是本地时间还是 UTC 的标志;它没有指定当地时间与 UTC 的实际偏移量。除了表明构造结构的意图之外,它还影响ToUniversalTime() 和ToLocalTime() 方法的工作方式。

【讨论】:

【参考方案9】:

聚会有点晚了,但我发现这两个链接 (4guysfromrolla) 非常有用:

Using Coordinated Universal Time (UTC) to Store Date/Time Values

Advice for Storing and Displaying Dates and Times Across Different Time Zones

【讨论】:

【参考方案10】:

DateTime.UtcNow 是一个省略夏令时的通用时间刻度。所以 UTC 永远不会因为 DST 而改变。

但是,DateTime.Now 不是连续的或单值的,因为它会根据 DST 变化。这意味着 DateTime.Now,相同的时间值可能会出现两次,使客户处于困惑状态。

【讨论】:

【参考方案11】:

如果您需要运行应用程序的机器的本地时间(例如欧洲的 CEST),请使用“现在”。如果您想要一个通用时间 - UtcNow。这只是您的偏好问题 - 可能会创建一个本地网站/独立应用程序,您希望使用用户拥有的时间 - 因此受到他/她的时区设置的影响 - DateTime.Now。

请记住,对于网站,它是服务器的时区设置。因此,如果您要为用户显示时间,要么获取他的首选时区并改变时间(只需将 Utc 时间保存到数据库,然后对其进行修改),要么指定它的 UTC。如果您忘记这样做,用户可能会看到类似的内容:3 个减号前发布,然后是未来的某个时间:)

【讨论】:

【参考方案12】:

DateTime.UtcNow 是一个连续的单值时间刻度,而 DateTime.Now 不是连续的或单值时间刻度。主要原因是夏令时,它不适用于 UTC。所以 UTC 永远不会向前或向后跳一小时,而本地时间 (DateTime.Now) 会。而当它向后跳时,同样的时间值会出现两次。

【讨论】:

【参考方案13】:

最大的区别 :) 是 SharePoint 工作流不支持 DateTime.Now,您必须使用 DateTime.UtcNow

【讨论】:

以上是关于DateTime.Now 与 DateTime.UtcNow的主要内容,如果未能解决你的问题,请参考以下文章

DateTime.Now 与 DateTime.UtcNow

DateTime.Now 和DateTime.UtcNow的区别

Xamarin.Forms DateTime.Now() 日期与当前日期不匹配

我可以获得与 DateTime.Now.Ticks 等效的 VBA 吗?

将 DateTime.Now 与 SQL Server 的开始时间和结束时间进行比较

Python3-datetime模块-日期与时间