存储DateTime(UTC)与存储DateTimeOffset


93

我通常有一个“拦截器”,在从数据库读取/写入数据库之前,它会进行DateTime转换(从UTC到本地时间,从本地时间到UTC),因此我可以DateTime.Now在整个系统中使用(派生和比较)而不必担心关于时区。

关于序列化和在计算机之间移动数据,无需费心,因为日期时间始终是UTC。

我应该继续以UTC格式存储日期(SQL 2008-datetime),还是应该使用DateTimeOffset(SQL 2008-datetimeoffset)存储日期?

数据库中的UTC日期(datetime类型)已经可以使用并且已经知道很长时间了,为什么要更改它?有什么优势?

我已经研究过类似这样的文章,但是我并不是100%确信。有什么想法吗?



1
另请参见:DateTime与DateTimeOffset-为.Net编写,但从概念上讲也适用于SQL。
Matt Johnson-Pint 2014年

Answers:


131

有一个巨大的区别,即您不能单独使用UTC。

  • 如果您有这样的情况

    • 一台服务器多个客户端(所有地理位置在不同的时区
    • 客户端使用日期时间信息创建一些数据
    • 客户端将其全部存储在中央服务器上
  • 然后:

    • datetimeoffset存储客户端的本地时间,还与UTC时间偏移
    • 所有客户都知道所有数据的UTC时间,以及信息产生地的本地时间
  • 但:

    • UTC datetime仅存储UTC datetime,因此您没有数据起源的客户端位置中有关本地时间的信息
    • 其他客户不知道该日期的信息来自何处
    • 其他客户端只能从数据库(使用UTC时间)计算其本地时间,而不能计算数据起源于客户端的本地时间

一个简单的例子就是机票预订系统。机票应包含2次:-“起飞”时间(在“来自”城市的时区中)-“着陆”时间(在“目的地”城市的时区中)


2
这是我读过的关于何时合适的最好的解释,对于我来说,我读了很多,从中看来,事实并非如此。我们在UTC上有时间获取外部数据,并且在需要时(也从未有过)从其他来源知道位置。感谢您让它看起来如此明显。
Andrew Backer 2012年

19
您说过“ datetimeoffset存储UTC时间和ALSO到客户端本地时间的偏移量”,但是datetimeoffset存储本地时间+偏移量,或者UTC时间+偏移量等于+0。
Serhii Kyslyi

尽管您可以将DTO转换为DT,因为DT的基础是UTC(尽管这对于每个使用数据库的人来说都是一个额外的步骤,并且可以说比仅仅使用UTC时间更简单)
iliketocode

2
似乎更像DateTmeOffset存储“本地时间和UTC偏移”,而不是“ UTC时间和UTC偏移”。如果转换为datetime或使用任何datepart函数,则将获取本地日期和时间组件。
Triynko

所有客户都知道所有数据的UTC时间,也知道信息起源地的本地时间。”尽管在这种情况下,存储为日期字段的一部分感觉很不规范。用例是什么-也就是说,为什么不使用UTC并向InputLocationId(或类似的标准化实体)拉出偏移量。涉及到计算(您好,异常 ...尤其是印第安纳州除外),但这仍然是确定性的过程-然后应用程序的日期时间逻辑的平衡就很简单了。
鲁芬

23

在所有历史时间(即记录事件发生)中都使用UTC是绝对正确的。从UTC到当地时间总是可能的,但并非总是相反。

什么时候使用当地时间?回答这个问题:

如果政府突然决定更改夏令时,您是否希望此数据随之更改?

如果答案为“是”,则仅存储本地时间。显然,这仅适用于将来的日期,通常仅适用于以某种方式影响人们的日期。

为什么要存储时区/偏移量?

首先,如果您想记录执行该操作的用户的偏移量,则最好这样做,即在登录时记录该用户的位置和时区。

其次,如果要转换为显示,则需要有一个表,其中包含该时区的所有本地时间偏移量转换,仅知道当前的偏移量是不够的,因为如果您显示六个月前的日期/时间,则偏移量将不一样


4
当夏令时更改为历史日期时,将考虑Windows UTC到本地时间的转换。我不知道您为什么要在这种情况下存储本地时间。
Jamiegs 2011年

1
@Jamiegs Windows仅在历史上知道“最新历史信息”(如.NET DateTime文档中所提示/所示)。它不全面。

2
当然,您还必须存储事件的位置,否则不能说事件发生在什么“本地时间”。
keuleJ

20

DATETIMEOFFSET使您能够在一个字段中存储本地时间和UTC时间。

这样就可以在本地或UTC时间进行非常简单有效的报告,而无需处理数据以任何方式显示。

这是两个最常见的要求-本地报告的本地时间和组报告的UTC时间。

本地时间存储在DATETIMEOFFSET的DATETIME部分中,UTC的OFFSET存储在OFFSET部分中,因此转换很简单,并且由于不需要了解数据来自的时区,因此可以在数据库级别完成所有操作。

如果您不需要毫秒以下的时间,例如几分钟或几秒钟,则可以使用DATETIMEOFFSET(0)。然后,DATETIMEOFFSET字段将仅需要8个字节的存储空间-与DATETIME相同。

因此,使用DATETIMEOFFSET而不是UTC DATETIME可以为报告提供更大的灵活性,效率和简便性。


太差劲的实体框架根本无法访问datetimeoffset字段的本地日期时间,从而无法查询特定的本地日期。
Triynko '16

@Triynko您能解释一下您的意思吗?例?
reidLinden '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.