DateTimeZone::listIdentifiers获取BV、HM时区返回空数组的解决办法
解决布韦岛(BV)和赫德岛(HM)时区获取为空的问题
我明白你遇到的困扰了——用DateTimeZone::listIdentifiers()按国家代码BV和HM查询时区时返回了空数组。这其实是因为这两个极小众的领地在PHP默认的时区数据库里没有被关联到具体的时区标识符,不过我们有几个实用的解决办法:
1. 手动映射小众地区的时区
布韦岛和赫德岛与麦克唐纳群岛实际上都采用UTC时区,所以最直接的方式是给这两个国家代码做硬编码映射:
// 小众国家/地区的时区映射表 $customCountryTimezones = [ 'BV' => ['UTC'], 'HM' => ['UTC'] ]; $timezoneIdentifiers = null; if($countryCode) { // 优先检查手动映射表 if (isset($customCountryTimezones[$countryCode])) { $timezoneIdentifiers = $customCountryTimezones[$countryCode]; } else { $timezoneIdentifiers = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $countryCode); } } else { $timezoneIdentifiers = DateTimeZone::listIdentifiers(); }
这种方式简单高效,适合处理这类明确知道时区的小众地区。
2. 引入第三方地理数据补充覆盖
如果你的应用需要处理更多小众国家/地区,可以借助第三方PHP包来扩展时区覆盖范围,比如league/iso3166(一个专注于ISO 3166国家代码标准的包)。你可以在原生查询的基础上,用第三方数据做 fallback:
use League\ISO3166\ISO3166; $iso3166 = new ISO3166(); $timezoneIdentifiers = null; if($countryCode) { // 先尝试原生PHP方法 $timezoneIdentifiers = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $countryCode); // 若结果为空,使用自定义映射补充 if (empty($timezoneIdentifiers)) { $fallbackTimezones = [ 'BV' => ['UTC'], 'HM' => ['UTC'] ]; $timezoneIdentifiers = $fallbackTimezones[$countryCode] ?? []; } } else { $timezoneIdentifiers = DateTimeZone::listIdentifiers(); }
这类包会更全面地覆盖国家代码信息,但对于极小众的无居民领地,还是需要你手动补充时区映射。
3. 设置UTC为通用 fallback
如果你的应用不需要精确到每个小众地区的特殊时区,也可以设置一个全局 fallback:当原生查询返回空数组时,默认返回UTC时区(毕竟很多无人居住的领地都采用UTC):
$timezoneIdentifiers = null; if($countryCode) { $timezoneIdentifiers = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $countryCode); // 为空时默认返回UTC if (empty($timezoneIdentifiers)) { $timezoneIdentifiers = ['UTC']; } } else { $timezoneIdentifiers = DateTimeZone::listIdentifiers(); }
为什么会返回空数组?
PHP的DateTimeZone::listIdentifiers()依赖于IANA时区数据库,而布韦岛、赫德岛这类人口极少甚至无人居住的领地,数据库没有为它们单独分配时区条目,因此按国家代码查询时会返回空数组。
内容的提问来源于stack exchange,提问作者Boris Aghajanyan
相关产品推荐
相关产品推荐

