有没有一种方法可以通过国家代码(有效的ISO-3166代码)获取时区?

16

我正在尝试为用户获取时区。

为此,我有一个国家代码,这是一个有效的ISO国家代码。这些代码是ISO-3166定义的大写两个字母代码。您可以在许多网站上找到完整的代码列表,例如: http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html

我认为回答是“不行,因为它是多对多关系...像美国这样的国家就可能有许多时区...” 这就是问题所在...

我已经尝试了一些类似于:

//CountryEnum contains ISO_3166 values (http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html) 
  //List all country to test timezone:
  for (int i = 0; i < CountryEnum.values().length; i++) {
   String isoCountryCode = CountryEnum.values()[i].name();// Get the iso country code
   Locale locale = new Locale(isoCountryCode);// Build a country specific locale
   Calendar calendar = Calendar.getInstance(locale);// Build a calendar with the specific locale
   String timeZone = calendar.getTimeZone().getDisplayName();// Build a timeZone with the calendar
   System.out.println("LOCALE : "+locale+" / COUNTRY: "+isoCountryCode+" / TIMEZONE: "+timeZone);
  }

但它总是返回服务器时区...

有什么想法吗?

7个回答

6
一个 Locale 不是一个 TimeZone,反之亦然。查看你正在使用的 Javadoc 方法-第一行就说了

使用默认时区和指定的语言环境获取日历。

这就是为什么当你获取一个日历时没有指定一个时区,所以得到的是默认时区。
想想Jon说的话-如果你知道在你已经确定用户来自美国的情况下想要使用哪个时区,那么你可以调用带有时区和语言环境参数的 Calendar.getInstance 方法。另一方面,如果你无法确定在此处要执行什么操作,那么请回到草稿并更多地考虑你的需求,而不是查看你的实现。
如果您无法回答之前的问题,我认为大多数网站的标准应对方法是允许用户指定其首选时区(如果他们在服务器上有持久帐户),并在未另行说明的情况下将其默认为服务器的时区。如果他们没有持久性帐户,并且他们正在向您提供带有时间信息的信息(例如XML上传),则他们将不得不在请求中指定他们正在使用的时区,或者(可能更好地)您强制使用UTC来表示所有时间。

不仅如此,而且单个参数的“Locale”构造函数指定的是语言,而不是国家。 - akf

5

1
这很方便,但返回的列表似乎是按名称字母顺序排列的;遗憾的是,ICU4J没有提供一种获取“国家代码最不出人意料的时区”以供显示目的的方法;很可能这是首都的时区。 - Richard Barnett

3

你说得很对。美国、俄罗斯和其他一些“大”国家(从东西方向上来看)并没有一个统一的时区。

以美国为例,你想使用哪个时区呢?America/Los_Angeles还是America/New_York?或者其他的?


1
有趣的是,还有其他只有一个时区的大国;印度和中国都属于这一类别。印度通常涵盖两个时区;中国则涵盖四个时区。 - Jonathan Leffler
2
是的 - 有些国家在处理时区问题时选择了理智的方式 :) - Jon Skeet
1
理智 - 是的;某种程度上。但在中国,如果太阳在东海岸早上5点升起,在戈壁沙漠西部边缘直到大约早上8点才会升起。如果在东海岸下午7点落日,那么在西部直到晚上10点才会落下。 - Jonathan Leffler
@Jonathan:我认为这很合理......而且在组织会议时不必考虑时区的好处是巨大的。我对时区有怨气 :) - Jon Skeet

0

我不知道有什么东西可以给你这个(正如Jon所指出的用例相当有限),但是你可以使用this data构建一个Map。列表将是一个多映射,因此您可能会使用来自Google Collections的多映射,或者使用您自己的ISO代码->List<String>映射。

给定时区字符串,您可以创建一个TimeZone对象并从那里开始。但是,如果该国家有多个时区,则必须决定如何处理。


没错,这对我来说是最好的解决方案。我认为我可能会将时区与国家映射,以便每个国家都有唯一的时区。 - ajeanson

-1

这里是您正在寻找的解决方案:

public String getTimeZoneByLocale(final String languageTag){
    final Locale locale = Locale.forLanguageTag(languageTag);
    final Calendar cal = Calendar.getInstance(locale);
    final TimeZone timeZone = cal.getTimeZone();
    return timeZone.getID();
}

languageTag 是像 en_US 或 ru_RU 这样的代码


不,这将返回 TimeZone.getDefault() - Arne Burmeister

-2

Olson数据库包含所有的映射。链接

搜索zone.tab文件。


-2
你尝试过TZInfo gem吗?
你可以通过以下方式获取一个国家的时区:
>> TZInfo::Country.get("DE").zone_identifiers
=> ["Europe/Berlin", "Europe/Busingen"]
>> TZInfo::Country.get("CN").zone_identifiers
=> ["Asia/Shanghai", "Asia/Harbin", "Asia/Chongqing", "Asia/Urumqi", "Asia/Kashgar"]
>> TZInfo::Country.get("US").zone_identifiers
=> ["America/New_York", "America/Detroit", "America/Kentucky/Louisville",   "America/Kentucky/Monticello", "America/Indiana/Indianapolis", "America/Indiana/Vincennes", "America/Indiana/Winamac", "America/Indiana/Marengo", "America/Indiana/Petersburg", "America/Indiana/Vevay", "America/Chicago", "America/Indiana/Tell_City", "America/Indiana/Knox", "America/Menominee", "America/North_Dakota/Center", "America/North_Dakota/New_Salem", "America/North_Dakota/Beulah", "America/Denver", "America/Boise", "America/Phoenix", "America/Los_Angeles", "America/Anchorage", "America/Juneau", "America/Sitka", "America/Yakutat", "America/Nome", "America/Adak", "America/Metlakatla", "Pacific/Honolulu"]

这是一个Java问题。 - Dónal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接