如何从标准DateTime
格式转换为UTC?
更具体地说,如果我在一个时区中创建一个DateTime
对象然后切换到另一个时区并在其上运行ToUniversalTime()
,它如何知道转换是否正确完成并且时间还是准确地代表了吗?
答案 0 :(得分:68)
DateTime
对象没有附加隐式时区。如果在其上运行ToUniversalTime()
,它将使用运行代码的上下文的时区。
例如,如果我从1970年1月1日的纪元创建一个DateTime
,无论我在世界的哪个地方,它都会给我相同的DateTime
对象。
如果我在格林威治运行代码时运行ToUniversalTime()
,那么我会得到相同的时间。如果我在温哥华居住的时候这样做,那么我得到的偏移DateTime
对象为-8小时。
这就是为什么在您需要进行任何类型的日期转换或本地化时,将时间相关信息作为UTC时间存储在数据库中的重要性。考虑您的代码库是否已移至另一个时区的服务器设施;)
编辑:来自Joel答案的注释 - 默认情况下DateTime
个对象输入为DateTimeKind.Local
。如果您解析日期并将其设置为DateTimeKind.Utc
,则ToUniversalTime()
不会执行转换。
以下是关于"Best Practices Coding with Date Times"的文章和关于Converting DateTimes with .Net的文章。
答案 1 :(得分:32)
首先,它检查Kind
的{{1}}是否已知为UTC。如果是这样,它将返回相同的值。
否则,它被假定为本地时间 - 它在运行的计算机的本地时间,特别是在某个私有财产首次被初始化时计算机正在使用的时区。这意味着如果您在应用程序启动后更改时区,那么它很可能仍然会使用旧的。
时区包含足够的信息,可以将本地时间转换为UTC时间,反之亦然,但有时会出现模糊或无效的情况。 (当地时间出现两次,当地时间由于夏令时而不会发生。)处理这些案件的规则在the documentation中指定:
如果日期和时间实例值是 一个模糊的时间,这种方法假设 这是一个标准时间。 (一个 模棱两可的时间是可以映射的时间 无论是标准时间还是标准时间 当地时间的夏令时 zone)如果是日期和时间实例 value是一个无效的时间,这个方法 只需减去当地时间 本地时区的UTC偏移量为 返回UTC。 (无效时间是一个 由于这个原因而不存在 应用夏令时 调整规则。)
返回的值的DateTime
为Kind
,因此如果您致电DateTimeKind.Utc
,则不会再次应用偏移量。 (这是对.NET 1.1的巨大改进!)
如果你想要一个非本地时区,你应该使用.NET 3.5中引入的TimeZoneInfo
(对于早期版本有一些hacky解决方案,但它们并不好)。要表示即时,您应该考虑使用.NET 2.0SP1,.NET3.0SP1和.NET 3.5中引入的DateTimeOffset
。但是,它仍然没有与之关联的实际时区 - 只是与UTC的偏移量。这意味着您不知道一个小时之后的当地时间,例如 - DST规则可能会在时区之间发生变化,而这些时区碰巧使用了特定时刻的相同偏移量。 ToUniveralTime
旨在将历史和未来规则考虑在内,而TimeZone
则相当简单。
基本上,.NET 3.5中的支持比它好很多,但仍然需要正确的日历算法。有人想把Joda Time移植到.NET吗? ;)
答案 2 :(得分:7)
什么是@womp said,另外还检查了DateTime的Kind属性,看它是否已经为UTC日期。
答案 3 :(得分:3)
DateTime.ToUniversalTime删除本地时区的时区偏移量,以将DateTime规范化为UTC。如果然后对另一个时区中的规范化值使用DateTime.ToLocalTime,则该时区的时区偏移量将被添加到规范化值中,以便在该时区中进行正确表示。