DateTime.ToUniversalTime和TimeZoneInfo.ConvertTimeToUtc之间有什么区别

Chr*_*rry 5 .net timezone datetime utc

凌晨6点,我刚开始正确思考如何推出一款需要在当天开始时向用户提供服务的网络应用程序.也是在他们的日子结束时.

无处不在我一直在阅读有关人们说很多只是用来.ToUniversalTime以UTC时间存储时间,但是当我尝试这个时(我怀疑)它没有用,它只是将时间缩短了一个小时(我在英国,所以我认为这与从GMT到UTC的一些偏差有关,虽然这对我来说没有意义,因为白天节能应该暂时关闭).

我在db中有一个存储用户时区的字段,所以当我开始使用ConvertTimeToUtc和fromUtc时,它开始做我期望它做的事情.虽然我不确定我是否必须自己构建一些逻辑以进行夏令时转换,或者它应该为我做.

我主要想知道为什么每个人都在谈论.ToUniversalTime,因为它似乎并没有帮助我,我无法理解它怎么可能知道多少来抵消将它转移到UTC的时间,而第二种方式有道理.

有人可以解释每种方法如何有用吗?

Mat*_*int 10

其实还有就是这两者之间的差异.

在.NET 3.5及更低版本中,Datetime.ToUniversalTime实现为:

public DateTime ToUniversalTime() {
    return TimeZone.CurrentTimeZone.ToUniversalTime(this);
}
Run Code Online (Sandbox Code Playgroud)

因为它使用了TimeZone该类,它遇到了MSDN文档中提到的相同问题:

TimeZone类支持本地时区只有一个日光节约时间的调整规则.因此,TimeZone班级可以准确报告夏令时信息,或仅在最新调整规则生效期间转换UTC和当地时间.相比之下,TimeZoneInfo该类支持多个调整规则,这使得可以使用历史时区数据.

在.NET 4.0及更高版本中,Datetime.ToUniversalTime实现为:

public DateTime ToUniversalTime() { 
    return TimeZoneInfo.ConvertTimeToUtc(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
} 
Run Code Online (Sandbox Code Playgroud)

这解决了不支持历史调整规则的问题,但由于该NoThrowOnInvalidTime标志,它与仅调用不同TimeZoneInfo.ConvertimeToUtc.

它调用的方法是带有标志的内部重载.该方法的公共版本使用,而这个使用.ConvertTimeToUtcTimeZoneInfoOptionsTimeZoneInfoOptions.NoneTimeZoneInfoOptions.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"
Run Code Online (Sandbox Code Playgroud)

VS:

DateTime dt = new DateTime(2015, 3, 8, 2, 0, 0, DateTimeKind.Local);
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt);  // throws exception!
Console.WriteLine(utc);
Run Code Online (Sandbox Code Playgroud)

由于在此日期,在此时区,时间从1:59:59跳至3:00:00,提供当地时间2:00:00无效.正确的做法是抛出异常(如第二种情况).但是,由于DateTime.ToUniversalTime早期框架版本的现有合同不允许这样做,因此框架选择返回值而不是抛出.

它选择的值是基于使用标准时间偏移计算的,就像没有发生DST转换一样.


wom*_*omp 2

如果您在不同时区的计算机上运行代码,您的计算仍然有效吗?这就是人们将所有日期时间存储并视为 UTC 的原因 - 它消除了任何歧义。您不需要存储用户的时区。任何地方的任何机器都可以从数据库中提取日期并轻松地将其与当地时间进行转换。

如果您将时间存储在其他时区,那么您必须将其取出,计算所需时区的偏移量,包括考虑夏令时和国际日期变更线的考虑因素。就您而言,您还存储了额外的不必要的信息。