我的数据库表中有一列UNIX时间戳,它来自科威特时区的系统。
数据库服务器的时区是Eastern Time US & Canada
。现在我需要使用SQL查询将UNIX时间戳转换为科威特时区日期值。
Unix时间戳是从UTC时间1970年1月1日开始的整数秒数。
假设你的意思是你的数据库中有一个整数列与这个数字,那么你的数据库服务器的时区是无关的。
首先将时间戳转换为datetime
类型:
SELECT DATEADD(second, yourTimeStamp, '1970-01-01')
这将是UTC datetime
,对应于你的时间戳。
那么您需要知道如何将此值调整为您的目标时区。在世界上的大部分地区,由于夏令时,一个区域可以有多个偏移。
遗憾的是,SQL Server不能直接工作时区。例如,如果你用的是美国太平洋时间,你就不知道应该减去7小时还是8小时。其他数据库(Oracle, Postgres, MySql等)有内置的方法来处理这个问题,但是,SQL Server没有。因此,如果您正在寻找通用解决方案,则需要执行以下操作之一:
将时区数据导入到表中,并在时区规则更改时维护该表。使用该表和一堆自定义逻辑来解析特定日期的偏移量
使用
xp_regread
获取包含时区数据的Windows注册表项,并再次使用一堆自定义逻辑来解决特定日期的偏移量。当然,xp_regread
是一件不好的事情,需要授予某些权限,并且不支持或文档。编写一个使用。net中
TimeZoneInfo
类的SQLCLR函数。不幸的是,这需要一个"不安全"的SQLCLR程序集,并且可能导致不好的事情发生。
恕我直言,这些方法都不是很好,并且没有好的解决方案可以直接在SQL中完成此操作。最好的解决方案是将UTC值(原始整数或UTC时的datetime
)返回给调用的应用程序代码,并在那里进行时区转换(例如,使用。net中的TimeZoneInfo
或其他平台中的类似机制)。
然而,你很幸运,因为科威特是(而且一直是)在一个不改变日光节约时间的区域。一直都是UTC+03:00。因此,您可以简单地添加三个小时并返回结果:
SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01'))
但是要认识到这不是一个通用的解决方案,它将在任何时区工作。
如果您愿意,您可以返回其他SQL数据类型之一,例如datetimeoffset
,但这只会帮助您反映该值对可能查看它的人有三个小时的偏移。它不会使转换过程有任何不同或更好。
更新答案
我创建了一个项目来支持SQL Server中的时区。你可以从这里安装它。然后你可以像这样简单地转换:
SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait')
您可以使用IANA tz数据库中的任何时区,包括使用夏令时的时区。
您仍然可以使用我上面展示的方法从unix时间戳进行转换。把它们放在一起:
SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait')
再次更新
在SQL Server 2016中,AT TIME ZONE
语句现在内置了对时区的支持。这在Azure SQL Database (v12)中也可用。
SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'
本公告中的更多示例