首页 > 解决方案 > 在 Java 中使用城市名称获取本地时区

问题描述

使用城市名称(例如。阿布扎比、悉尼、达卡、巴黎等)需要找到当地时区。可使用 2 位国家代码

标签: javatimezonetimezone-offsetcity

解决方案


对于涵盖所有可以想到的城市名称的解决方案,这将需要一个包含城市及其相应时区的数据库。存在同名城市的事实将进一步复杂化,因此您可能有模棱两可的输入。例如,巴黎,我想你指的是法国的首都和最大的城市,欧洲,但其他地方也存在名为巴黎的城镇。不知道有没有合适的数据库,你可以搜索一下。

不过,我可以让您了解 Java 中内置的内容。时区具有区域/城市形式的 ID ,例如Australia/SydneyAsia/Dubai。用于命名时区的城市是该时区人口最多的地区,因此即使一个国家或州只有一个时区,城市也不必是首都。但是如果城市重合,我们可以找到该区域。

    Set<String> zids = ZoneId.getAvailableZoneIds();

    String[] cityNames = { "Abu Dhabi", "Dubai", "Sydney", "Dhaka", "Paris", "Indianapolis", "São Tomé" };
    for (String cityName : cityNames) {
        String tzCityName = Normalizer.normalize(cityName, Normalizer.Form.NFKD)
                .replaceAll("[^\\p{ASCII}-_ ]", "")
                .replace(' ', '_');
        List<String> possibleTimeZones = zids.stream()
                .filter(zid -> zid.endsWith("/" + tzCityName))
                .collect(Collectors.toList());
        System.out.format("%-12s %s%n", cityName, possibleTimeZones);
    }

此代码段的输出是:

Abu Dhabi    []
Dubai        [Asia/Dubai]
Sydney       [Australia/Sydney]
Dhaka        [Asia/Dhaka]
Paris        [Europe/Paris]
Indianapolis [America/Indianapolis, America/Indiana/Indianapolis]
São Tomé     [Africa/Sao_Tome]

但是,您会注意到它没有找到阿布扎比的任何时区,因为虽然它是阿拉伯联合酋长国的首都,但它不是最大的城市;迪拜是。您还会注意到为印第安纳波利斯找到了两个时区。不过,前者只是后者的别名。

时区数据库中使用的城市名称是去掉任何重音的英文名称(如果存在)。当名称由两个或三个单词组成时,它们用下划线而不是空格分隔。所以圣多美成为圣多美。因此,在代码中我正在执行此转换。去除重音的方法取自另一个 Stack Overflow 答案,链接如下。

链接


推荐阅读