如何从标准 DateTime 格式转换为UTC?

更具体地说,如果我在一个时区创建 DateTime 对象,然后切换到另一个时区并在其上运行 ToUniversalTime(),它是如何知道的转换是否正确完成,时间仍然准确表示?

有帮助吗?

解决方案

DateTime 对象没有附加隐式时区。如果在其上运行 ToUniversalTime(),它将使用运行代码的上下文的时区。

例如,如果我从1970年1月1日的纪元创建 DateTime ,无论我在世界的哪个地方,它都会给我相同的 DateTime 对象

如果我在格林威治运行代码时运行 ToUniversalTime(),那么我会得到相同的时间。如果我在温哥华住的时候这样做,那么我得到一个-8小时的偏移 DateTime 对象。

这就是为什么在您需要进行任何类型的日期转换或本地化时,将时间相关信息作为UTC时间存储在数据库中的重要性。考虑您的代码库是否已移至另一个时区的服务器设施;)

编辑:来自Joel答案的注释 - DateTime 对象默认情况下输入为 DateTimeKind.Local 。如果您解析日期并将其设置为 DateTimeKind.Utc ,则 ToUniversalTime()不会执行任何转换。

这是一篇关于“带日期时间的最佳实践编码”的文章,以及有关使用.Net转换日期时间的文章。

其他提示

首先,它检查 DateTime Kind 是否已知为UTC。如果是这样,它将返回相同的值。

否则,它被假定为本地时间 - 它在运行的计算机的本地时间,特别是在某个私有财产首次被初始化时计算机正在使用的时区。这意味着如果您在应用程序启动后更改时区,那么它很可能仍然会使用旧的。

时区包含足够的信息,可以将本地时间转换为UTC时间,反之亦然,但有时会出现模糊或无效的情况。 (当地时间出现两次,当地时间从未因夏令时而发生。)处理这些情况的规则在文档

  

如果日期和时间实例值是   一个模糊的时间,这种方法假设   这是一个标准时间。 (一个   模棱两可的时间是可以映射的时间   无论是标准时间还是标准时间   当地时间的夏令时   zone)如果是日期和时间实例   value是一个无效的时间,这个方法   只需减去当地时间   本地时区的UTC偏移量为   返回UTC。 (无效时间是一个   由于这个原因而不存在   应用夏令时   调整规则。)

返回的值将具有 KindTimeKind.Utc Kind ,因此如果您调用 ToUniveralTime ,则不会应用偏移量再次。 (这是对.NET 1.1的巨大改进!)

如果您需要非本地时区,则应使用 <代码> TimeZoneInfo 是在.NET 3.5中引入的(对于早期版本有一些hacky解决方案,但它们并不好)。要及时表示,您应该考虑使用 DateTimeOffset ,它是在.NET 2.0SP1,.NET3.0SP1和.NET 3.5中引入的。但是,它仍然没有与之关联的实际时区 - 只是与UTC的偏移量。这意味着您不知道一个小时之后的当地时间,例如 - DST规则可能会在时区之间发生变化,而这些时区碰巧使用了特定时刻的相同偏移量。 TimeZoneInfo 旨在将历史和未来规则考虑在内,而不是 TimeZone ,这有点过分了。

基本上,.NET 3.5中的支持比它好很多,但仍然需要正确的日历算法。有人想把 Joda Time 移植到.NET吗? ;)

@womp说,另外还检查DateTime的Kind属性以查看它是否可能已经是UTC日期。

DateTime.ToUniversalTime删除本地时区的时区偏移量,以将DateTime规范化为UTC。如果然后对另一个时区中的规范化值使用DateTime.ToLocalTime,则该时区的时区偏移量将被添加到规范化值中,以便在该时区中进行正确表示。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top