我一直想知道这两个属性的工作原理究竟是什么.我知道第二个是通用的,基本上不处理时区,但是有人可以详细解释它们是如何工作的以及应该在什么情况下使用哪一个?
DateTime.UtcNow告诉你协调世界时的日期和时间,它也被称为格林威治标准时间时区 - 基本上就像你在英国伦敦,但不是在夏天.DateTime.Now给出了当前语言环境中某人所看到的日期和时间.
我建议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.UtcNow的用处非常有用.也就是说,在参与夏令时的地方,有时从第二天中午到中午有25个小时,有时在第二天中午和中午之间有23个小时.如果要正确确定从时间A和时间B开始的小时数,则需要在计算TimeSpan之前首先将每个小时转换为其UTC等效值.
我写的博客文章涵盖了这一点,进一步解释了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值更改为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 = Utc的DateTime对象,除非在i/o(显示和解析)期间.这意味着你应该几乎总是使用DateTime.UtcNow,除了你创建对象只是为了显示它的情况,并立即丢弃它.
DateTime不知道时区是什么.它总是假设你在当地时间.UtcNow仅表示"从时间中减去我的时区".
如果要使用时区感知日期,请使用DateTimeOffset,它表示带有时区的日期/时间.我不得不学习那种艰难的方式.