DateTime.Now与DateTime.UtcNow


Answers:


346

DateTime.UtcNow会告诉您日期和时间,与协调世界时一致,也称为格林威治标准时区-基本上就像您在英国伦敦一样,但不在夏季。DateTime.Now提供在您当前语言环境中的日期和时间。

我建议DateTime.Now您在向人类显示日期时使用-这样,他们便会与他们看到的价值相适应-这是他们可以轻松将其与手表或时钟上看到的东西进行比较的东西。使用DateTime.UtcNow时要存储日期或将其用于以后计算这样(在客户机-服务器模式)你的计算不要被从你的服务器或彼此不同的时区的客户混淆。


84
一个很好的观点- 日期存储在数据库或文件中时,一定要将它们存储在UTC中!
杰夫·阿特伍德

15
您必须注意,当您要将日期存储在数据库中的UTC时,必须确保数据库不会在没有给出明确时区的日期中添加自己的时区。请注意,当要求DateTime时,它将始终使用当前时区。
Omer van Kloeten

@OmervanKloeten提出了一个很好的观点。我想知道是否有一个优雅的“全面”解决方案,即使您的IIS和SQL Server所在的时区不同,每次也都能正确地存储和接收日期。
TheGeekZn 2014年

1
@ JoshYates1980是的,您只需要执行DateTime.UtcNow.AddYears(1)
CathalMF

3
使用NodaTime-它会迫使您以更有用的方式考虑时间并避免此类问题
aateeque

86

这确实非常简单,所以我认为这取决于您的受众群体和居住地。

如果您不使用Utc,则必须知道向其显示日期和时间的人员所在的时区-否则,您将告诉他们系统或服务器时间在下午3点发生了什么,而实际上是在下午5点发生了什么,他们碰巧活着。

我们之所以使用DateTime.UtcNow我们,是因为我们拥有全球的网络受众,并且因为我不希望每个用户都填写表格来指明他们所居住的时区。

我们还会显示相对时间(2小时前,1天前等),直到帖子老化为止,无论您居住在地球上的哪个地方,时间都是“相同的”。


我还想第二次仅在完成2个日期的计算以获取正确的小时数时才需要存储DateTime.UtcNow。当我只需要显示RegisterAt Date时,那么Datetime.Now就足够了。
伊丽莎白2016年

36

还要注意性能差异;比快30DateTime.UtcNow左右,因为在内部进行了很多时区调整(您可以使用Reflector轻松地进行验证)。DateTime.NowDateTime.Now

因此,请勿DateTime.Now用于相对时间测量。


知道UtcNow性能更好并且仅将您的日期保存在mysql中并假设它是utc并将与日期相关的显示与UtcNow进行比较简化了这个全球时区问题,这让我经历了一段痛苦的旅程
Diin

29

一个主要的概念在.NET难以理解的是,现在现在地球上各地不论你是在那么什么时区,如果您加载一个变量,DateTime.NowDateTime.UtcNow-分配是相同的*您DateTime对象知道什么时区你是在并考虑到这一点,无论分配如何。

DateTime.UtcNow在跨夏时制时间边界计算日期时,的用处会很方便。也就是说,在参与夏时制的地方,有时从第二天的中午到第二天的中午有25个小时,有时在第二天的中午到中午有23个小时。如果要正确确定从时间A和时间B开始的小时数,则需要先将每个小时转换为它们的UTC等效时间,然后再计算TimeSpan

我写一篇博客文章对此做了进一步介绍TimeSpan,并对此做了进一步解释,其中包括指向该主题的MS文章的链接。

*说明:任何一项分配都会存储当前时间。如果要加载两个变量,一个通过DateTime.Now(),另一个通过两个之间DateTime.UtcNow()TimeSpan差值将是毫秒,而不是几个小时(假设您所在的时区距离GMT数小时)。如下所述,打印出它们的String值将显示不同的字符串。


1
关于“使用DateTime.Now或DateTime.UtcNow加载变量-分配是相同的”:这可能需要澄清吗?当我坐在EDT时区(UTC -4)时,我分别向DateTime.UtcNow和DateTime.Now分配了两个变量,然后使用ToString()打印它们的值。显示的值相隔4小时-不是“相同”。
乔恩·施耐德

2
@JonSchneider,我相信你是正确的。语句:“分配相同”是不正确的。ToString()可能不是测试它的最佳方法,因为它可能以不同的方式显示相等的日期(就像Java一样)。比较函数是更好的测试,表明它们确实不相等。
Ted Bigham

澄清我的“相同”语句:通过DateTime.Now加载一个变量,并使用DateTime.UtcNow加载另一个变量,然后打印TimeSpan差异。假设您距离格林威治标准时间数小时,则差异将是毫秒而不是小时。
卡尔相机

18

这是一个很好的问题。我正在恢复它,以提供更多有关.Net在不同Kind值下的行为的详细信息。正如@Jan Zich指出的那样,它实际上是至关重要的属性,并且根据您使用Now还是设置不同的属性UtcNow

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

DateTime.UtcNow表现得和其他语言一样。它设置Ticks为基于GMT的值。它还设置KindUtc

DateTime.NowTicks值更改为在格林尼治标准时间时区的一天中的时间。它还设置KindLocal

如果您比格林威治标准时间(GMT-6)晚6个小时,则您将从6个小时前获得格林尼治标准时间。Kind尽管实际上应该是“现在”,但.Net实际上忽略并视这次为6小时前。如果创建DateTime实例,然后更改时区并尝试使用它,则此中断会更大。

具有不同“种类”值的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 <now”应该是正确的(可以肯定的是,我什至还加了一个小时),但是仍然是错误的。

您还可以看到“解决方法”,它可以简单地将世界各地的时间转换为通用时间Kind

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


7

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

如果要使用可识别时区的日期,请使用DateTimeOffset,它表示带有时区的日期/时间。我必须努力学习。


9
确切地说(出于性能原因,避免人们在Now over UtcNow上使用Now),这是另一回事:Now将时区添加到UtcNow中,实际上幅度要慢一些。
mafu 2012年

5

该问题的“简单”答案是:

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

DateTime.UtcNow返回一个DateTime值,该值表示当前的世界标准时间(aka UTC),无论系统时区如何,该时间都相同。该DateTime.Kind属性将为DateTimeKind.Utc


4

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



1

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


1

DateTime.UtcNow是一种通用时标,省略了夏时制。因此,UTC永远不会因为DST而改变。

但是,DateTime.Now不是连续的或单值的,因为它会根据DST进行更改。这意味着DateTime.Now,同一时间值可能出现两次,使客户处于混乱状态。


0

当您需要在本地运行计算机时(例如欧洲的CEST),请使用Now。如果您想要一个世界通用时间-UtcNow。只是您的喜好问题-可能制作一个您想使用用户时间的本地网站/独立应用程序-因此受其时区设置-DateTime.Now的影响。

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.