Azure Maps 和 SQL AT TIME ZONE 与夏威夷的时区不兼容
Azure Maps and SQL AT TIME ZONE incompatible time zone for Hawaii
我只是 运行 在使用 Azure Maps 为时区提供的数据尝试使用 AT TIME ZONE
在 SQL 服务器(Azure SQL)中获取本地时间时出现问题].
当我向 Azure Maps 提供夏威夷位置的 lat/long 数据时,return 显示 "Hawaii-Aleutian Standard Time":
"Names":{
"ISO6391LanguageCode":"en",
"Generic":"Hawaii-Aleutian Time",
"Standard":"Hawaii-Aleutian Standard Time",
"Daylight":"Hawaii-Aleutian Daylight Time"
},
在我系统的另一部分,我需要能够确定 SQL 服务器中该位置的本地时间,因此我使用 AT TIME ZONE
并注入标准时区。这适用于我正在处理的美国时区,例如 "Eastern Standard Time" 或 "Central Standard Time"。当它到达夏威夷位置时...它出错并说它不是一个有效的时区。
查看我在网上找到的 SQL 服务器的时区列表,看来夏威夷在 SQL 的时区是 "Hawaiian Standard Time"。
还有其他人 运行 遇到这种情况吗?
我想我需要修正一些异常代码,以用 "Hawaiian Standard Time" 替换这个 Azure 提供的时区。有更好的解决方案吗?
这里有一个示例供参考 URL(减号):https://atlas.microsoft.com/timezone/byCoordinates/json?subscription-key={key}&api-version=1.0&options=all&query=21.4500,-158.0054
这是完整的 JSON returned:
{
"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"
}
]
}
]
}
好的,"Pacific/Honolulu" 是 IANA 代码。根据一些 SQL 文档,它支持所有 Windows 时区,而其他文档说它只支持机器注册表中的时区,这可能因机器而异。物理检查我的机器我可以看到 SQL 支持 137 个时区(Select * 来自 sys.time_zone_info)。然而,根据 Windows 文档,它有 250 个默认时区(加上一些扩展时区)。在某些地方肯定存在断开连接,但它看起来更像是 Windows/SQL 断开连接。
也就是说,"Hawaiian Standard Time" 和 "Hawaii-Aleutian Standard Time" 似乎是相同的:https://www.timeanddate.com/time/zones/hast
然而,当谈到夏令时时,它变得更加复杂:https://www.timeanddate.com/time/zones/hadt
我会将此线程传递给 Azure Maps 工程和数据团队进行更深入的调查。
Names
部分返回的字符串不是标识符。它们是源自 Unicode CLDR 的本地化字符串,旨在向最终用户显示。虽然其中一些在以英文呈现时可能与标识符对齐,但不能保证这一点。
它们也不是随意选择的。 "Hawaii-Aleutian Time" 确实是这个时区的法定名称,由 15 USC 260 (and described on Wikipedia here) 定义。
另一方面,SQL 服务器的时区功能严格依赖于 Windows 时区标识符,可以在 Windows 注册表中找到,或者通过各种 APIs(例如 .NET 的 TimeZoneInfo.Id
)和命令行实用程序(例如 TZUTIL /L
返回的每对结果的第一行)。
不幸的是,Azure Maps API 目前似乎只有 returns IANA ID,而不是相应的 Windows ID。我已经要求 Azure Maps API 团队考虑在未来的版本中添加它。
同时,您可以将IANA ID转换为对应的Windows ID,然后再在SQL服务器中使用。假设您在 .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" />
您只需使用 TZID
和 WinID
属性在该方向进行映射。
或者,您可以使用 CLDR 的 /common/supplemental/windowsZones.xml
文件,因为这是权威来源。开发主干版本位于 here。其数据看起来相似,但属性命名不同:
<mapZone other="Hawaiian Standard Time" territory="001" type="Pacific/Honolulu"/>
我只是 运行 在使用 Azure Maps 为时区提供的数据尝试使用 AT TIME ZONE
在 SQL 服务器(Azure SQL)中获取本地时间时出现问题].
当我向 Azure Maps 提供夏威夷位置的 lat/long 数据时,return 显示 "Hawaii-Aleutian Standard Time":
"Names":{
"ISO6391LanguageCode":"en",
"Generic":"Hawaii-Aleutian Time",
"Standard":"Hawaii-Aleutian Standard Time",
"Daylight":"Hawaii-Aleutian Daylight Time"
},
在我系统的另一部分,我需要能够确定 SQL 服务器中该位置的本地时间,因此我使用 AT TIME ZONE
并注入标准时区。这适用于我正在处理的美国时区,例如 "Eastern Standard Time" 或 "Central Standard Time"。当它到达夏威夷位置时...它出错并说它不是一个有效的时区。
查看我在网上找到的 SQL 服务器的时区列表,看来夏威夷在 SQL 的时区是 "Hawaiian Standard Time"。
还有其他人 运行 遇到这种情况吗?
我想我需要修正一些异常代码,以用 "Hawaiian Standard Time" 替换这个 Azure 提供的时区。有更好的解决方案吗?
这里有一个示例供参考 URL(减号):https://atlas.microsoft.com/timezone/byCoordinates/json?subscription-key={key}&api-version=1.0&options=all&query=21.4500,-158.0054
这是完整的 JSON returned:
{
"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"
}
]
}
]
}
好的,"Pacific/Honolulu" 是 IANA 代码。根据一些 SQL 文档,它支持所有 Windows 时区,而其他文档说它只支持机器注册表中的时区,这可能因机器而异。物理检查我的机器我可以看到 SQL 支持 137 个时区(Select * 来自 sys.time_zone_info)。然而,根据 Windows 文档,它有 250 个默认时区(加上一些扩展时区)。在某些地方肯定存在断开连接,但它看起来更像是 Windows/SQL 断开连接。
也就是说,"Hawaiian Standard Time" 和 "Hawaii-Aleutian Standard Time" 似乎是相同的:https://www.timeanddate.com/time/zones/hast
然而,当谈到夏令时时,它变得更加复杂:https://www.timeanddate.com/time/zones/hadt
我会将此线程传递给 Azure Maps 工程和数据团队进行更深入的调查。
Names
部分返回的字符串不是标识符。它们是源自 Unicode CLDR 的本地化字符串,旨在向最终用户显示。虽然其中一些在以英文呈现时可能与标识符对齐,但不能保证这一点。
它们也不是随意选择的。 "Hawaii-Aleutian Time" 确实是这个时区的法定名称,由 15 USC 260 (and described on Wikipedia here) 定义。
另一方面,SQL 服务器的时区功能严格依赖于 Windows 时区标识符,可以在 Windows 注册表中找到,或者通过各种 APIs(例如 .NET 的 TimeZoneInfo.Id
)和命令行实用程序(例如 TZUTIL /L
返回的每对结果的第一行)。
不幸的是,Azure Maps API 目前似乎只有 returns IANA ID,而不是相应的 Windows ID。我已经要求 Azure Maps API 团队考虑在未来的版本中添加它。
同时,您可以将IANA ID转换为对应的Windows ID,然后再在SQL服务器中使用。假设您在 .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" />
您只需使用 TZID
和 WinID
属性在该方向进行映射。
或者,您可以使用 CLDR 的 /common/supplemental/windowsZones.xml
文件,因为这是权威来源。开发主干版本位于 here。其数据看起来相似,但属性命名不同:
<mapZone other="Hawaiian Standard Time" territory="001" type="Pacific/Honolulu"/>