在sql server中从时区到时区的日期时间转换

Ash*_*ore 15 timezone unix-timestamp sql-server-2012

我的数据库表中有一列UNIX时间戳,它来自科威特时区的系统.

我的数据库服务器的时区是Eastern Time US & Canada.现在我需要使用SQL查询将UNIX时间戳转换为科威特时区日期值.

谁能告诉我如何将这个UNIX时间戳转换为科威特时区的日期值?

Mat*_*int 27

Unix时间戳是自1970年1月1日UTC以来的整数秒数.

假设您的意思是数据库中有一个带有此数字的整数列,那么数据库服务器的时区就无关紧要了.

首先将时间戳转换为datetime类型:

SELECT DATEADD(second, yourTimeStamp, '1970-01-01')
Run Code Online (Sandbox Code Playgroud)

这将是datetime与您的时间戳对应的UTC .

然后,您需要知道如何将此值调整为目标时区.在世界大部分地区,由于夏令时,单个区域可以有多个偏移.

遗憾的是,SQL Server无法直接处理工作时区.因此,如果您使用美国太平洋时间,您将无法知道是否应减去7小时或8小时.其他数据库(Oracle,Postgres,MySql等)有内置的方法来处理这个问题,但唉,SQL Server没有.因此,如果您正在寻找通用解决方案,则需要执行以下操作之一:

  • 将时区数据导入表中,并在时区规则更改时维护该表.将该表与一堆自定义逻辑一起使用来解析特定日期的偏移量.

  • 使用xp_regread得到的含有时区数据在Windows注册表项,并再次使用一堆定制逻辑来解决特定日期的偏移量.当然,这xp_regread是一件坏事,需要授予某些权限,并且不受支持或记录.

  • 编写一个使用TimeZoneInfo.Net中的类的SQLCLR函数.不幸的是,这需要一个"不安全"的SQLCLR程序集,并可能导致不良事件发生.

恕我直言,这些方法都不是很好,并且没有很好的解决方案直接在SQL中执行此操作.最好的解决方案是将UTC值(原始整数或datetimeUTC)返回给调用的应用程序代码,然后在那里进行时区转换(例如,TimeZoneInfo在.Net或其他平台中的类似机制) .

但是 - 你很幸运,科威特(并且一直都是)在一个夏令时不变的区域.它一直是UTC + 03:00.所以你可以简单地添加三个小时并返回结果:

SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01'))
Run Code Online (Sandbox Code Playgroud)

但请注意,这不是一个适用于任何时区的通用解决方案.

如果您愿意,可以返回其他SQL数据类型之一,例如datetimeoffset,但这只会帮助您反映该值是三小时偏移给任何人可能会看到它.它不会使转换过程有任何不同或更好.


更新的答案

我已经创建了一个支持SQL Server时区的项目.你可以从这里安装它.然后你可以像这样简单地转换:

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait')
Run Code Online (Sandbox Code Playgroud)

您可以使用IANA tz数据库中的任何时区,包括使用夏令时的数据库.

您仍然可以使用我上面显示的方法从unix时间戳转换.将它们放在一起:

SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait')
Run Code Online (Sandbox Code Playgroud)

再次更新

使用SQL Server 2016,现在可以使用该AT TIME ZONE语句内置对时区的支持.Azure SQL数据库(v12)中也提供了此功能.

SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'
Run Code Online (Sandbox Code Playgroud)

本公告中有更多例子.

  • 好吧,如果要在应用程序中使用`DateTimeOffset`,那么切换偏移是好的.但如果你只是回到'datetime`,那么就没有真正的附加好处.你可能只需要增加3个小时. (2认同)