为什么Azure会丢失DateTimeOffset字段中的时区信息?

时间:2016-02-16 21:01:31

标签: sql-server azure datetimeoffset

我们正在使用Microsoft的Azure移动服务开发IOS应用程序。 Web GUI将日期时间创建为DateTimeOffset字段,这很好。但是当我们将移​​动设备将日期时间放入数据库时​​,然后通过实体框架从数据库中读取它们,我们将它们调整为UCT。 (当我们在SSMS中查看记录时,我们会看到同样的事情。)

我一直对SQL的标准日期时间类型缺乏时区支持感到沮丧,我认为DateTimeOffset会更好。但如果我想要我在UTC的时间,我会把它们存储在UTC中。如果用户在CST上午3:00输入时间,我想知道他进入了CST。将它转换为UTC并丢弃偏移量对我来说没有多大意义,因为它假设CST凌晨3点和PDT凌晨3点是相同的。

我是否可以使用某种数据库配置来保持Azure数据库不以UTC格式存储日期?

2 个答案:

答案 0 :(得分:2)

问题是,在Azure移动服务中的某个时刻,该属性将转换为JavaScript Date对象,该对象无法保留偏移量。

有几篇博客文章描述了这个问题,以及可能的解决方法:

基本上,他们都采用相同的方法将偏移分割成单独的字段。然而,仔细观察这些,他们都犯了一个重要的错误:

dto.DateTime.ToUniversalTime()

实际应该是:

dto.UtcDateTime

DateTime的{​​{1}}始终为DateTimeOffset,因此DateTimeKind.Unspecified会认为来源是本地,而非使用DTO的抵消。

我在这些帖子的代码中看到了一些其他类似的错误,所以要小心彻底测试。然而,一般的方法是合理的。

答案 1 :(得分:0)

我们正在使用Node.js后端,并注意到同样的事情,我们的SQL Server数据库中的DATETIMEOFFSET读取是以UTC返回的,无论偏移量如何。另一种方法是在查询级别转换DATETIMEOFFSET,以便将其作为带有时区信息的字符串输出。以下内容将DATETIMEOFFSET(0)字段转换为ISO8601格式;但是,其他可能的样式可以用作记录here

SELECT CONVERT(VARCHAR(33), [StartDate], 126) AS [StartDate] FROM [Products];

新输出现在是:"2016-05-26T00:00:00-06:00"而不是"2016-05-26T06:00:00+00:00"

当然,这意味着客户端必须将字符串序列化为各自的格式。在iOS中,ISO8601库可用于将输出读取为NSDateComponentsNSDate

此方法的一个好处是,任何数据库级别的检查或触发器都可以使用DATETIMEOFFSET进行日期比较,而不是尝试考虑具有基本DATETIME的单独偏移列。