15

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

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

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

4

1 回答 1

27

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

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

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

SELECT DATEADD(second, yourTimeStamp, '1970-01-01')

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

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

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

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

  • 用于xp_regread获取包含时区数据的 Windows 注册表项,并再次使用一堆自定义逻辑来解决特定日期的偏移量。当然,xp_regread这样做是一件坏事,需要授予某些权限,并且不支持或文档。

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

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

但是-您很幸运,科威特(并且一直)处于夏令时不变的区域。一直是 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')

再次更新

AT TIME ZONE在 SQL Server 2016 中,现在通过语句内置了对时区的支持。这在 Azure SQL 数据库 (v12) 中也可用。

SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'

本公告中的更多示例。

于 2013-06-01T15:07:02.760 回答