我刚刚开始正确思考如何在一天开始时推出一个需要为用户做事的网络应用程序,比如早上6点。也是在他们的日子结束时。
我到过的每个地方都在阅读有关人们说很多只是要使用.ToUniversalTime以UTC时间存储时间,但是当我尝试这个时(我怀疑)它没有用,它只是移动了时间一个小时(我在英国,所以我认为这与从格林威治标准时间到UTC的一些偏差有关,虽然这对我来说没有意义,因为白天节能应该暂时关闭)。
我在db中有一个存储用户时区的字段,所以当我开始使用ConvertTimeToUtc和fromUtc时,它开始做我期望它做的事情。虽然我不知道自己是否必须建立一些逻辑来进行夏令时转换,或者它应该为我做。
我主要想知道为什么每个人都在谈论.ToUniversalTime,因为它似乎并没有帮助我,我无法理解它怎么可能知道多少来抵消将它转移到UTC的时间,而第二种方式是有道理的。
有人可以解释每种方法的用途吗?
答案 0 :(得分:9)
实际上是这两者之间的区别。
在.NET 3.5及更低版本中,Datetime.ToUniversalTime
实现为:
public DateTime ToUniversalTime() {
return TimeZone.CurrentTimeZone.ToUniversalTime(this);
}
因为它使用了TimeZone
类,所以它遇到了the MSDN docs中提到的相同问题:
TimeZone
类仅支持本地时区的单个夏令时调整规则。因此,TimeZone
类可以准确地报告夏令时信息,或仅在最新调整规则生效期间在UTC和本地时间之间进行转换。相比之下,TimeZoneInfo
类支持多个调整规则,这使得可以使用历史时区数据。
在.NET 4.0及更高版本中,Datetime.ToUniversalTime
实现为:
public DateTime ToUniversalTime() {
return TimeZoneInfo.ConvertTimeToUtc(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
}
这解决了不支持历史调整规则的问题,但由于NoThrowOnInvalidTime
标记,与仅调用TimeZoneInfo.ConvertimeToUtc
不一样。
它调用的方法是ConvertTimeToUtc
的内部重载,它带有TimeZoneInfoOptions
标志。该方法的 public 版本使用TimeZoneInfoOptions.None
,而此版本使用TimeZoneInfoOptions.NoThrowOnInvalidTime
。
差异可以说明如下。将时区设置为美国太平洋时间:
DateTime dt = new DateTime(2015, 3, 8, 2, 0, 0, DateTimeKind.Local);
DateTime utc = dt.ToUniversalTime();
Console.WriteLine(utc); // "3/8/2015 10:00:00 AM"
Vs的:
DateTime dt = new DateTime(2015, 3, 8, 2, 0, 0, DateTimeKind.Local);
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt); // throws exception!
Console.WriteLine(utc);
由于在此日期,在此时区内,时间从1:59:59跳至3:00:00,提供当地时间2:00:00无效。正确的做法是抛出异常(如第二种情况)。但是,由于早期框架版本的现有DateTime.ToUniversalTime
合同不允许这样做,因此框架选择返回值而不是抛出。
它选择的值是基于使用标准时间偏移计算的,就像没有发生DST转换一样。
答案 1 :(得分:2)
如果您在不同时区的计算机上运行代码,您的计算是否仍然有效?这就是人们将所有DateTimes存储和处理为UTC的原因 - 它消除了任何歧义。您不需要存储用户的时区。任何地方的任何机器都可以从数据库中提取日期并轻松地将其转换为本地时间。
如果您在其他时区存储时间,则必须将其拉出,计算到所需时区的偏移量,包括考虑夏令时和国际日期时间因素。在您的情况下,您还存储了额外的不必要信息。
答案 2 :(得分:2)
DateTime.ToUniversalTime
和TimeZoneInfo.ConvertTimeToUtc
的实施之间的细微差别。
对于标题中有特定问题的其他人: DateTime.ToUniversalTime和TimeZoneInfo.ConvertTimeToUtc 之间的区别是什么?
答案是:没有区别。
使用JustDecompile检查.NET 4.5中DateTime.ToUniversalTime
的实现,我们发现它直接使用TimeZoneInfo.ConvertTimeToUtc
:
public DateTime ToUniversalTime()
{
return TimeZoneInfo.ConvertTimeToUtc(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
}