DateTime.Now 与 DateTime.Now日期时间.UtcNow
-
09-06-2019 - |
题
我一直想知道这两个属性的工作原理到底是什么。我知道第二个是通用的,基本上不涉及时区,但是有人可以详细解释它们是如何工作的以及在什么情况下应该使用哪一个?
解决方案
日期时间.UtcNow 告诉您协调世界时(也称为格林威治标准时间)时区的日期和时间 - 基本上就像您在英国伦敦一样,但不是在夏季。 日期时间.现在 给出在您当前区域中的人看来的日期和时间。
我建议使用 DateTime.Now
每当您向人们显示日期时(这样他们就会对所看到的值感到满意),他们可以轻松地将日期与他们在手表或时钟上看到的值进行比较。使用 DateTime.UtcNow
当您想要存储日期或将它们用于以后的计算时(在客户端-服务器模型中),您的计算不会因与服务器不同时区的客户端或彼此之间的客户端而混淆。
其他提示
这真的很简单,所以我认为这取决于你的受众是谁以及他们住在哪里。
如果您不使用 Utc,则 必须 知道您要向其显示日期和时间的人的时区 - 否则您会告诉他们在系统或服务器时间中下午 3 点发生了某事,而实际上事情发生在他们碰巧居住的下午 5 点。
我们用 DateTime.UtcNow
因为我们拥有全球网络受众,并且因为我不想让每个用户填写表格来表明他们居住的时区。
我们还会显示相对时间(2 小时前、1 天前等),直到帖子足够老,无论您住在地球上的哪个地方,时间都是“相同的”。
还要注意性能差异;DateTime.UtcNow 比 DateTime.Now 快大约 30 倍,因为 DateTime.Now 内部正在进行大量时区调整(您可以使用 Reflector 轻松验证这一点)。
因此,不要使用 DateTime.Now 进行相对时间测量。
在 .NET 中需要理解的一个主要概念是 现在 是 现在 遍布地球,无论您位于哪个时区。所以如果你加载一个变量 DateTime.Now
或者 DateTime.UtcNow
-- 作业是相同的。* 您的 DateTime
对象知道您所在的时区,并且无论分配如何,都会考虑到这一点。
的用处 DateTime.UtcNow
在计算跨夏令时边界的日期时会派上用场。即参加夏令时的地方,有时中午到次日中午有25个小时,有时中午到次日中午有23个小时。如果您想正确确定时间 A 和时间 B 之间的小时数,则需要先将每个时间转换为其 UTC 等效值,然后再计算 TimeSpan
.
这由一个 我写的博文 这进一步解释了 TimeSpan
, ,并包含有关该主题的更广泛的 MS 文章的链接。
*澄清:任一分配都会存储当前时间。如果您要加载两个变量,其中一个通过 DateTime.Now()
另一个通过 DateTime.UtcNow()
这 TimeSpan
假设您所在的时区距离格林威治标准时间有几个小时,两者之间的差异将是毫秒,而不是几个小时。如下所述,打印出它们的 String
值将显示不同的字符串。
这是一个很好的问题。我正在恢复它,以提供有关 .Net 如何与不同的行为的更多细节 Kind
价值观。正如 @Jan Zich 指出的,它实际上是一个非常重要的属性,并且根据您是否使用而设置不同 Now
或者 UtcNow
.
在内部日期存储为 Ticks
(与@Carl Camera的答案相反)取决于您是否使用 Now
或者 UtcNow
.
DateTime.UtcNow
行为方式与其他语言类似。它设置 Ticks
为基于 GMT 的值。它还设置 Kind
到 Utc
.
DateTime.Now
改变 Ticks
价值 如果这是您一天中格林尼治标准时间 (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
本来应该快1个小时了,结果却快6个小时了。“utc < now”应该是真的(我什至添加了一个小时以确保),但仍然是假的。
您还可以看到“解决方法”,即在任何地方简单地转换为世界时间 Kind
不一样。
我对这个问题的直接回答与已接受的答案关于何时使用每一个的建议一致。你应该永远 尝试 跟...共事 DateTime
具有的对象 Kind=Utc
, ,除了 I/O 期间(显示和解析)。这意味着您几乎应该始终使用 DateTime.UtcNow
, ,除了您创建对象只是为了显示它并立即丢弃它的情况。
DateTime 不知道什么是时区。它始终假设您处于当地时间。 即时通讯 只意味着“从时间中减去我的时区”。
如果您想使用时区感知日期,请使用 日期时间偏移量, ,它表示带有时区的日期/时间。我必须通过艰难的方式才能学会这一点。
这个问题的“简单”答案是:
日期时间.现在 返回一个 约会时间 表示当前系统时间的值(无论系统运行在哪个时区)。这 日期时间.种类 财产将是 日期时间种类.Local
日期时间.UtcNow 返回一个 约会时间 表示当前通用协调时间(又名 UTC)的值,无论系统位于哪个时区,该值都相同。这 日期时间.种类 财产将是 日期时间种类.Utc
DateTime.UtcNow 是连续的单值时间刻度,而 DateTime.Now 不是连续的或单值的。主要原因是夏令时,它不适用于 UTC。因此,UTC 永远不会向前或向后跳一小时,而本地时间 (DateTime.Now) 却会。并且当它向后跳跃时,相同的时间值出现两次。
DateTime.UtcNow 是省略夏令时的通用时间刻度。所以 UTC 永远不会因为 DST 而改变。
但是,DateTime.Now 不是连续的或单值的,因为它根据 DST 变化。这意味着 DateTime.Now,相同的时间值可能会出现两次,让客户处于困惑状态。
当您需要运行应用程序的计算机的当地时间(例如欧洲的 CEST)时,请使用 Now。如果您想要通用时间 - UtcNow。这只是您的偏好问题 - 可能制作一个您想要使用用户拥有的时间的本地网站/独立应用程序 - 因此受到他/她的时区设置的影响 - DateTime.Now。
请记住,对于网站来说,它是服务器的时区设置。因此,如果您要为用户显示时间,请获取他的首选时区并更改时间(只需将 Utc 时间保存到数据库中,然后进行修改)或指定它是 UTC。如果您忘记这样做,用户可能会看到类似以下内容的内容: 缺点 3 年前发布 然后是在未来的某个时间附近:)