...有时对于(UTC+01:00) West Central Africa 时区,我会得到这些值Africa/Lagos 和Africa/Luanda。
没错。您提到的 Windows 时区有多个有效的 IANA 时区映射。 Unicode CLDR 是这些映射的权威,您可以在windowsZones.xml 文件中查看,目前看起来像这样:
<!-- (UTC+01:00) West Central Africa -->
<mapZone other="W. Central Africa Standard Time" territory="001" type="Africa/Lagos"/>
<mapZone other="W. Central Africa Standard Time" territory="AO" type="Africa/Luanda"/>
<mapZone other="W. Central Africa Standard Time" territory="BJ" type="Africa/Porto-Novo"/>
<mapZone other="W. Central Africa Standard Time" territory="CD" type="Africa/Kinshasa"/>
<mapZone other="W. Central Africa Standard Time" territory="CF" type="Africa/Bangui"/>
<mapZone other="W. Central Africa Standard Time" territory="CG" type="Africa/Brazzaville"/>
<mapZone other="W. Central Africa Standard Time" territory="CM" type="Africa/Douala"/>
<mapZone other="W. Central Africa Standard Time" territory="DZ" type="Africa/Algiers"/>
<mapZone other="W. Central Africa Standard Time" territory="GA" type="Africa/Libreville"/>
<mapZone other="W. Central Africa Standard Time" territory="GQ" type="Africa/Malabo"/>
<mapZone other="W. Central Africa Standard Time" territory="NE" type="Africa/Niamey"/>
<mapZone other="W. Central Africa Standard Time" territory="NG" type="Africa/Lagos"/>
<mapZone other="W. Central Africa Standard Time" territory="TD" type="Africa/Ndjamena"/>
<mapZone other="W. Central Africa Standard Time" territory="TN" type="Africa/Tunis"/>
<mapZone other="W. Central Africa Standard Time" territory="ZZ" type="Etc/GMT-1"/>
在大多数情况下,列出的所有 IANA 区域都是等效的,并且都与给定的 Windows 区域对齐。 Africa/Lagos 被 CLDR 指定为“黄金地带”(territory="001")。通常,当国家代码可用时,实现应使用国家代码特定映射,否则使用黄金地带。
...因为我使用的是countries-and-timezones,所以它没有非洲/罗安达作为安哥拉的时区...
通过查看该特定包的 GitHub 源,尚不清楚其数据的来源。而且,它已经3年没有更新了。如果没有定期更新和明确的来源,此类软件包通常没有用处(恕我直言)。
...当我查看 Momentjs 的打包 data.json 文件时,我发现了这个:“Africa/Lagos|Africa/Luanda”。而且这不是唯一正在更新的时区,还有很多。
确实,Moment-timezone 将链接等效区域。要认识到的一个实现细节是,时刻不一定将“黄金地带”放在首位。它只是按字母顺序排列,当它看到两个具有相同数据的区域时,它会将它们组合起来。这相对不重要,因为时区本身确实具有相同的数据(偏移量、转换和缩写匹配)。
如何从 Moment.tz.guess() 函数中获取原始值 Africa/Lagos。
嗯,这里没有“原始”价值,所以你不能。原始值将是 Windows 时区(“W. Central Africa Standard Time”)。 Moment 首先尝试使用 JavaScript Intl API 直接从您的浏览器获取 IANA 时区 ID - 因此根据实现,浏览器可以返回 any 等效时区 ID。因此,一些实现可能会给出Africa/Lagos,一些可能会给出Africa/Luanda,或者该区域的 CLDR 映射中的任何其他实现。
对于不存在 Intl API 的实现,moment.tz.guess 将根据其拥有的数据(无论您加载什么)测试您本地时区的偏移量,并选择一个匹配的。如果出现平局,则包含一些关于人口的额外数据,以选择更常见的数据。您可以在 moment-timezone 文档和源代码中 moment.tz.guess 函数的实现中了解这些详细信息。
请记住,仅仅因为您在不同的环境中从moment.tz.guess 得到不同的结果并不意味着这些结果是无效的。您应该仍然可以使用返回给您的任何结果。
或者有没有更好的库来从时区获取国家代码...
我还不知道有一个维护良好的 JavaScript 库可以方便地为您做到这一点。我很想创建一个(就像我已经为 .NET 所做的那样),但与此同时,您可以阅读 JSON version of the CLDR mapping file 并自己解析它。
...因为我无法使用 timezonedb 或 ip-api 之类的任何服务从 IP 地址获取国家/地区代码...
除了 IP 地址之外,您还可以考虑是否有可用的纬度/经度位置?如果是这样,请查看列出的方法 in this question 了解如何使用它来获取时区 ID。