夏威夷的Azure Maps和SQL AT TIME ZONE时区不兼容

时间:2018-12-07 16:31:05

标签: sql-server azure timezone azure-maps

在使用Azure Maps提供的时区尝试使用AT TIME ZONE来获取SQL Server(Azure SQL)中的本地时间的数据时,我遇到一个问题。

当我将Azure纬度/经度数据提供给夏威夷位置时,返回消息为“夏威夷-阿留申标准时间”:

"Names":{  
        "ISO6391LanguageCode":"en",
        "Generic":"Hawaii-Aleutian Time",
        "Standard":"Hawaii-Aleutian Standard Time",
        "Daylight":"Hawaii-Aleutian Daylight Time"
     },

在系统的另一部分中,我需要能够确定SQL Server中该位置的本地时间,因此我正在使用AT TIME ZONE并注入标准时区。这对于我正在处理的美国时区(例如“东部标准时间”或“中央标准时间”)非常有用。当到达夏威夷地点时,它会出错并说这不是有效的时区。

查看我可以在线找到的SQL Server时区列表,看来夏威夷在SQL中的时区是“夏威夷标准时间”。

还有其他人遇到这种断开连接吗?

我认为我需要纠正一些异常代码,才能用“夏威夷标准时间”替换此Azure提供的时区。有更好的解决方案吗?

作为参考,下面是一个示例URL(减号):https://atlas.microsoft.com/timezone/byCoordinates/json?subscription-key={key}&api-version=1.0&options=all&query=21.4500,-158.0054

这是返回的完整JSON:

{
  "Version": "2018g",
  "ReferenceUtcTimestamp": "2018-12-08T17:10:31.8007137Z",
  "TimeZones": [
    {
      "Id": "Pacific/Honolulu",
      "Aliases": [
        "Pacific/Johnston",
        "US/Hawaii"
      ],
      "Countries": [
        {
          "Name": "United States",
          "Code": "US"
        },
        {
          "Name": "US minor outlying islands",
          "Code": "UM"
        }
      ],
      "Names": {
        "ISO6391LanguageCode": "en",
        "Generic": "Hawaii-Aleutian Time",
        "Standard": "Hawaii-Aleutian Standard Time",
        "Daylight": "Hawaii-Aleutian Daylight Time"
      },
      "ReferenceTime": {
        "Tag": "HST",
        "StandardOffset": "-10:00:00",
        "DaylightSavings": "00:00:00",
        "WallTime": "2018-12-08T07:10:31.8007137-10:00",
        "PosixTzValidYear": 2018,
        "PosixTz": "HST+10"
      },
      "RepresentativePoint": {
        "Latitude": 21.306944444444444,
        "Longitude": -157.85833333333332
      },
      "TimeTransitions": [
        {
          "Tag": "HST",
          "StandardOffset": "-10:00:00",
          "DaylightSavings": "00:00:00",
          "UtcStart": "1947-06-08T12:30:00Z",
          "UtcEnd": "9999-12-31T23:59:59.9999999Z"
        }
      ]
    }
  ]
}

2 个答案:

答案 0 :(得分:2)

Names部分中返回的字符串不是标识符。它们是源自Unicode CLDR的本地化字符串,旨在显示给最终用户。尽管其中一些可能会以英语显示时与标识符对齐,但并不能保证如此。

它们也不是任意选择的。根据15 USC 260(and described on Wikipedia here)的定义,“夏威夷-阿留申时间”确实是该时区的法定名称。

另一方面,SQL Server的时区功能严格依赖Windows时区标识符(可以在Windows注册表中找到),也可以通过各种API(例如.NET的TimeZoneInfo.Id)和命令行实用程序(例如在TZUTIL /L返回的每对结果的第一行上。

不幸的是,看来Azure Maps API当前仅返回IANA ID,而不返回相应的Windows ID。我已经要求Azure Maps API团队考虑在以后的版本中添加它。

同时,您可以将IANA ID转换为相应的Windows ID,然后再在SQL Server中使用它。假设您使用的是.NET应用程序,最简单的方法是使用我的TimeZoneConverter库:

string tz = TZConvert.IanaToWindows("Pacific/Honolulu");  //=>  "Hawaiian Standard Time"

如果您不在.NET中,则可以在以下路径使用Windows内置文件:

C:\Windows\Globalization\Time Zone\timezoneMapping.xml

文件中的条目如下所示:

<MapTZ TZID="Pacific/Honolulu" WinID="Hawaiian Standard Time" Region="001" Default="true" StdPath="Hawaii_Aleutian/standard" DltPath="Hawaii_Aleutian/daylight" />

您只需使用TZIDWinID属性来朝该方向进行映射。

或者,您可以使用CLDR的/common/supplemental/windowsZones.xml文件,因为这是权威来源。开发主干版本位于here。它的数据看起来相似,但是属性的名称不同:

<mapZone other="Hawaiian Standard Time" territory="001" type="Pacific/Honolulu"/>

答案 1 :(得分:1)

好的,“ Pacific / Honolulu”是IANA代码。根据一些SQL文档,它支持所有Windows时区,而其他文档则说它仅支持计算机注册表中的时区,这可能因计算机而异。从物理上检查我的机器,我可以看到SQL支持137个时区(从sys.time_zone_info中选择*)。但是,根据Windows文档,它具有250个默认时区(以及大量扩展时区)。某些地方肯定存在断开连接,但看起来更像Windows / SQL断开连接。

也就是说,“夏威夷标准时间”和“夏威夷-阿留申标准时间”似乎是相同的:https://www.timeanddate.com/time/zones/hast

但是,关于夏时制,它变得更加复杂:https://www.timeanddate.com/time/zones/hadt

我将把该线程传递给Azure Maps工程和数据团队进行更深入的研究。