Java中的时区
我允许我的web应用程序上的用户根据他们选择的时区安排活动 我想向最终用户展示一个很好的时区列表,然后在服务器端将其轻松转换为Java中的时区,java,timezone,Java,Timezone,我允许我的web应用程序上的用户根据他们选择的时区安排活动 我想向最终用户展示一个很好的时区列表,然后在服务器端将其轻松转换为java.util.TimeZone对象 String[]TimeZone.getAvailableIds()是我可以使用的东西,但问题是它打印了大约585个时区ID 向用户呈现时区简要列表(如用于时区设置的Windows框)并使用其id轻松转换为服务器端的时区对象的最佳方式是什么?您不能使用使用“GMT+/-小时”符号(跳过分钟)的自定义时区id列表吗 (编辑:根据我的
java.util.TimeZone
对象
String[]TimeZone.getAvailableIds()
是我可以使用的东西,但问题是它打印了大约585个时区ID
向用户呈现时区简要列表(如用于时区设置的Windows框)并使用其id轻松转换为服务器端的时区对象的最佳方式是什么?您不能使用使用“GMT+/-小时”符号(跳过分钟)的自定义时区id列表吗 (编辑:根据我的第一个建议,夏令时转换不是自动的。要解决此问题,您可以首先要求用户选择GMT偏移,然后使用以下命令显示给定偏移的时区ID(链接)列表:
public static String[] getAvailableIDs(int rawOffset)
这样,用户就可以在一个更短的列表中选择自己的时区(更好的用户体验),并从夏令时行为中获益。如果您需要精确选择列表外观的粒度,我将使用我能找到的最佳硬编码列表()并确保其显示和转换尽可能精确
请记住,这585个时区中的每一个都有语义含义(例如DST),用户可能希望为它们选择最佳时区。虽然我同意这个列表可以短得多。时区列表非常适合应用程序和特定区域。只有您知道哪些区域最适合您的用户。事实上,我们有不同地区的不同列表 这是我们的列表,供美国用户参考
"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",
我这样做是为了一家我不再拥有的公司,所以无法提供代码。Windows上的JVM附带一个名为
tzmappings
(查看C:\Program Files\Java\jre6\lib
或类似内容)的文件,该文件将Windows时区映射到Java基于zoneinfo的大陆/城市表单
不幸的是,
tzmappings
中的文本名称非常糟糕,因此您需要做几分钟的制表工作。打开regedit并导航到HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
。下面是机器上每个时区的一个键;Windows7大约有90个用户。每个键都有一个名为Display
的值,这是您想要的文本名称;在tzmappings
中查找键本身,找到每个键的Java时区标识符 有这么多,我不会把它们塞进选择框列表中。。。。我会将它们放在一个单独的模式对话框(或者弹出窗口,如果你必须的话)的列表中,让用户滚动浏览并单击他们想要的名称。他们会在模式对话框中点击一个链接,它会用正确的代码填充一个文本字段,然后您可以将其提交给服务器
更好的办法是,让他们在世界地图上点击自己的位置,并使用图像地图将该位置转换为适当的时区 您可以使用仅与以下regexp匹配的TZ id来减少列表
^(Africa|America|Asia|Atlantic|Australia|Europe|Indian|Pacific)/.*
我刚刚编写了一个小型Java实用程序,它提供了Windows时区列表(Windows中时区选择对话框中的区域)及其关联的Java时区对象。看
这是基于的CLDR映射,只是为了补充tbruyelle的答案,我又添加了几个国家(如加拿大),删除了过滤器的“/”部分,并提供了对列表进行排序的方法
public static void main(String[] args)
{
List<String> simplifiedTimezoneList = getTimezoneIdList();
for (String tz : simplifiedTimezoneList)
System.out.println(tz);
}
public static List<String> getTimezoneIdList()
{
String[] temp = TimeZone.getAvailableIDs();
List<String> timezoneList = new ArrayList<String>();
List<String> simplifiedTimezoneList = new ArrayList<String>();
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;
}
publicstaticvoidmain(字符串[]args)
{
List simplifiedTimezoneList=GetTimeZoneId列表();
for(字符串tz:simplifiedTimezoneList)
系统输出打印LN(tz);
}
公共静态列表getTimezoneIdList()
{
字符串[]temp=TimeZone.getAvailableIDs();
List timezoneList=new ArrayList();
List simplifiedTimezoneList=新建ArrayList();
用于(字符串tz:temp)
{
时区列表添加(tz);
}
集合。排序(时区列表);
String filterList=“加拿大|墨西哥|智利|古巴|巴西|日本|土耳其|中东|非洲|美洲|亚洲|大西洋|澳大利亚|欧洲|印度|太平洋”;
模式p=Pattern.compile(“^(“+filterList+”).*”);
用于(字符串tz:时区列表)
{
匹配器m=p.匹配器(tz);
if(m.find())
{
简化时区列表。添加(tz);
}
}
返回simplifiedTimezoneList;
}
ZoneId
TimeZone
类现在是遗留类,几年前被JSR310中定义的现代java.time类所取代。具体地被替换为
大多数当前使用的时区的名称格式为大陆/地区
。看到一个排序表
获取所有时区名称的列表
Set<String> zoneIds = ZoneId.getAvailableZoneIds() ;
System.out.println( "zoneIds = " + zoneIds );
如中所述,缩小向用户展示的列表的一种方法是在大陆上过滤部分。其中,我认为最好关注以下方面:
- 欧洲
- 非洲
- 南极洲
- 大西洋
- 美国
- 太平洋的
- 印第安人
- 澳大利亚
…加上添加Etc/UTC
在Java代码中,按字母顺序排序
List < String > zoneGroupNames = List.of(
"Africa" ,
"Antarctica" ,
"Atlantic" ,
"America" ,
"Australia" ,
"Europe" ,
"Indian" ,
"Pacific" ,
"UTC"
);
将键映射到值集合称为“多重映射”。我们现在有了内置的multimap功能,并将Map
实现与Java捆绑在一起。打电话(见附件)
显示该组的区域名称列表。假设用户选择项目#12(索引11),当前为Europe/Malta
Map < String, List < String > > mapGroupNameToZoneNames = new TreeMap <>();
String zoneNameChosenByUser = zoneNamesOfGroup.get( 11 ); // Malta
从该区域名称的字符串中创建一个ZoneId
对象
ZoneId zoneIdChosenByUser = ZoneId.of( zoneNameChosenByUser );
zoneIdChosenByUser.toString()=欧洲/马耳他
谢谢是的,但是使用它创建的java.util.TimeZone不会自动考虑夏令时。如果我使用:TimeZone.getTimeZone(“America/Los_Angeles”)创建时区,那么我就不需要担心DST等问题,还是我弄错了?你是对的
String groupNameChosenByUser = zoneGroupNames.get( 5 ); // Europe
List < String > zoneNamesOfGroup = mapGroupNameToZoneNames.get( groupNameChosenByUser );
String zoneNameChosenByUser = zoneNamesOfGroup.get( 11 ); // Malta
ZoneId zoneIdChosenByUser = ZoneId.of( zoneNameChosenByUser );