我一直想知道这两个属性的工作原理到底是什么。我知道第二个是通用的,基本上不涉及时区,但是有人可以详细解释它们的工作原理以及在哪种情况下应该使用哪个?
我一直想知道这两个属性的工作原理到底是什么。我知道第二个是通用的,基本上不涉及时区,但是有人可以详细解释它们的工作原理以及在哪种情况下应该使用哪个?
Answers:
DateTime.UtcNow会告诉您日期和时间,与协调世界时一致,也称为格林威治标准时区-基本上就像您在英国伦敦一样,但不在夏季。DateTime.Now提供在您当前语言环境中的日期和时间。
我建议DateTime.Now
您在向人类显示日期时使用-这样,他们便会与他们看到的价值相适应-这是他们可以轻松将其与手表或时钟上看到的东西进行比较的东西。使用DateTime.UtcNow
时要存储日期或将其用于以后计算这样(在客户机-服务器模式)你的计算不要被从你的服务器或彼此不同的时区的客户混淆。
这确实非常简单,所以我认为这取决于您的受众群体和居住地。
如果您不使用Utc,则必须知道向其显示日期和时间的人员所在的时区-否则,您将告诉他们系统或服务器时间在下午3点发生了什么,而实际上是在下午5点发生了什么,他们碰巧活着。
我们之所以使用DateTime.UtcNow
我们,是因为我们拥有全球的网络受众,并且因为我不希望每个用户都填写表格来指明他们所居住的时区。
我们还会显示相对时间(2小时前,1天前等),直到帖子老化为止,无论您居住在地球上的哪个地方,时间都是“相同的”。
还要注意性能差异;比快30倍DateTime.UtcNow
左右,因为在内部进行了很多时区调整(您可以使用Reflector轻松地进行验证)。DateTime.Now
DateTime.Now
因此,请勿DateTime.Now
用于相对时间测量。
一个主要的概念在.NET难以理解的是,现在是现在地球上各地不论你是在那么什么时区,如果您加载一个变量,DateTime.Now
或DateTime.UtcNow
-分配是相同的*您DateTime
对象知道什么时区你是在并考虑到这一点,无论分配如何。
DateTime.UtcNow
在跨夏时制时间边界计算日期时,的用处会很方便。也就是说,在参与夏时制的地方,有时从第二天的中午到第二天的中午有25个小时,有时在第二天的中午到中午有23个小时。如果要正确确定从时间A和时间B开始的小时数,则需要先将每个小时转换为它们的UTC等效时间,然后再计算TimeSpan
。
我写的一篇博客文章对此做了进一步介绍TimeSpan
,并对此做了进一步解释,其中包括指向该主题的MS文章的链接。
*说明:任何一项分配都会存储当前时间。如果要加载两个变量,一个通过DateTime.Now()
,另一个通过两个之间DateTime.UtcNow()
的TimeSpan
差值将是毫秒,而不是几个小时(假设您所在的时区距离GMT数小时)。如下所述,打印出它们的String
值将显示不同的字符串。
这是一个很好的问题。我正在恢复它,以提供更多有关.Net在不同Kind
值下的行为的详细信息。正如@Jan Zich指出的那样,它实际上是至关重要的属性,并且根据您使用Now
还是设置不同的属性UtcNow
。
在内部,日期存储为Ticks
哪个日期(与@Carl Camera的答案相反),具体取决于您使用Now
还是UtcNow
。
DateTime.UtcNow
表现得和其他语言一样。它设置Ticks
为基于GMT的值。它还设置Kind
为Utc
。
DateTime.Now
将Ticks
值更改为在格林尼治标准时间时区的一天中的时间。它还设置Kind
为Local
。
如果您比格林威治标准时间(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
,除了创建对象只是为了显示它并立即丢弃它的情况。
DateTime不知道什么时区。它始终假定您在本地时间。UtcNow仅表示“从时间中减去我的时区”。
如果要使用可识别时区的日期,请使用DateTimeOffset,它表示带有时区的日期/时间。我必须努力学习。
该问题的“简单”答案是:
DateTime.Now返回一个DateTime值,该值表示当前的系统时间(在系统运行的任何时区中)。该DateTime.Kind属性将为DateTimeKind.Local
DateTime.UtcNow返回一个DateTime值,该值表示当前的世界标准时间(aka UTC),无论系统时区如何,该时间都相同。该DateTime.Kind属性将为DateTimeKind.Utc
除了上述几点外,DateTime结构还包含一个名为Kind的鲜为人知的字段(至少,我很长一段时间都不了解它)。它基本上只是一个标志,指示时间是本地时间还是UTC。它未指定本地时间与UTC的实际偏移量。除了表明构造意图的意图这一事实之外,它还影响方法ToUniversalTime()和ToLocalTime()的工作方式。