Java中的时区

我允许用户在我的网络应用上根据自己选择的时区安排活动。

我想向最终用户提供一个很好的时区列表,然后将其轻松转换为服务器端的java.util.TimeZone对象。

String[] TimeZone.getAvailableIds()是我可以使用的,但问题是它打印了大约585个时区ID。

向用户提供简短的时区列表(如Windows区域用于时区设置)以及使用其ID在服务器端轻松转换为TimeZone对象的最佳方法是什么?

时区列表非常适用于应用程序和区域设置。 只有您知道哪些区域最适合您的用户。 我们实际上有不同地区的不同名单。

以下是我们的美国用户列表供您参考,

  "Pacific/Midway", "US/Hawaii", "US/Alaska", "US/Pacific", "America/Tijuana", "US/Arizona", "America/Chihuahua", "US/Mountain", "America/Guatemala", "US/Central", "America/Mexico_City", "Canada/Saskatchewan", "America/Bogota", "US/Eastern", "US/East-Indiana", "Canada/Eastern", "America/Caracas", "America/Manaus", "America/Santiago", "Canada/Newfoundland", "Brazil/East", "America/Buenos_Aires", "America/Godthab", "America/Montevideo", "Atlantic/South_Georgia", "Atlantic/Azores", "Atlantic/Cape_Verde", "Africa/Casablanca", "Europe/London", "Europe/Berlin", "Europe/Belgrade", "Europe/Brussels", "Europe/Warsaw", "Africa/Algiers", "Asia/Amman", "Europe/Athens", "Asia/Beirut", "Africa/Cairo", "Africa/Harare", "Europe/Helsinki", "Asia/Jerusalem", "Europe/Minsk", "Africa/Windhoek", "Asia/Baghdad", "Asia/Kuwait", "Europe/Moscow", "Africa/Nairobi", "Asia/Tbilisi", "Asia/Tehran", "Asia/Muscat", "Asia/Baku", "Asia/Yerevan", "Asia/Kabul", "Asia/Yekaterinburg", "Asia/Karachi", "Asia/Calcutta", "Asia/Colombo", "Asia/Katmandu", "Asia/Novosibirsk", "Asia/Dhaka", "Asia/Rangoon", "Asia/Bangkok", "Asia/Krasnoyarsk", "Asia/Hong_Kong", "Asia/Irkutsk", "Asia/Kuala_Lumpur", "Australia/Perth", "Asia/Taipei", "Asia/Tokyo", "Asia/Seoul", "Asia/Yakutsk", "Australia/Adelaide", "Australia/Darwin", "Australia/Brisbane", "Australia/Sydney", "Pacific/Guam", "Australia/Hobart", "Asia/Vladivostok", "Asia/Magadan", "Pacific/Auckland", "Pacific/Fiji", "Pacific/Tongatapu", 

我刚刚编写了一个小型Java实用程序,它提供了Windows时区列表(Windows中时区选择对话框中的区域)及其关联的Java TimeZone对象。 请参阅https://github.com/nfergu/Java-Time-Zone-List

这基于http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml上的CLDR映射

您可以使用仅与以下正则表达式匹配的TZ ID来减少列表

 ^(Africa|America|Asia|Atlantic|Australia|Europe|Indian|Pacific)/.* 

为了补充tbruyelle的答案,我添加了一些国家(例如加拿大),删除了filter的“/”部分并提供了对列表进行排序的方法。

 public static void main(String[] args) { List simplifiedTimezoneList = getTimezoneIdList(); for (String tz : simplifiedTimezoneList) System.out.println(tz); } public static List getTimezoneIdList() { String[] temp = TimeZone.getAvailableIDs(); List timezoneList = new ArrayList(); List simplifiedTimezoneList = new ArrayList(); for (String tz : temp) { timezoneList.add(tz); } Collections.sort(timezoneList); String filterList = "Canada|Mexico|Chile|Cuba|Brazil|Japan|Turkey|Mideast|Africa|America|Asia|Atlantic|Australia|Europe|Indian|Pacific"; Pattern p = Pattern.compile("^(" + filterList + ").*"); for (String tz : timezoneList) { Matcher m = p.matcher(tz); if (m.find()) { simplifiedTimezoneList.add(tz); } } return simplifiedTimezoneList; } 

如果您需要精确选择列表的外观,我会使用我能找到的最好的硬编码列表( 这是一个很好的例子 ),并确保尽可能精确地显示和转换它。

请记住,这585个时区中的每一个都具有语义含义(例如DST),用户可能希望为它们选择最佳时区。 虽然我同意列表可以更短。

您是否可以使用“GMT +/-小时”表示法(跳过分钟)来使用自定义时区ID列表?

(编辑:根据我的第一个建议,夏令时转换不是自动的。要解决此问题,您可以先要求用户选择GMT偏移,然后使用以下方法显示给定偏移的(链接)时区ID列表:

 public static String[] getAvailableIDs(int rawOffset) 

这样,用户就可以在较短的列表中选择他的时区(更好地为用户体验),并从夏令时行为中受益。)

我为一家我不再拥有的公司做了这个,所以无法提供代码。 Windows上的JVM附带了一个名为tzmappings的文件(查看C:\Program Files\Java\jre6\lib或类似文件),该文件将Windows时区映射到Java的基于zoneinfo的Continent / City表单。

不幸的是, tzmappings中的文本名称很糟糕,所以你需要做几分钟的制表。 打开注册表并导航到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones 。 在这下面是机器上每个时区的关键; Windows 7大约有90个。每个键都有一个名为Display的值,它是您想要的文本名称; 在tzmappings中查找密钥本身,以查找每个密钥的Java时区标识符。

有了这么多,我不会试着将它们变成一个选择框列表……我会把它们放在一个单独的modal dialog中的列表中(或弹出,如果你必须的话),让用户滚动并点击他们想要的名字。 他们会点击modal dialog中的链接,然后使用正确的代码填充文本字段,然后您可以将其提交给您的服务器。

更好的是,让他们在世界地图上点击他们的位置,并使用图像地图将该位置转换为适当的时区。