我有一个Android应用程序,它使用TimeZone.getAvailableIDs()
来提取所有可用的时区ID字符串。这些 ID 将保存到 ArrayList
中,如下所示:
ArrayList<String> clocks = new ArrayList<>();
String[] ids = TimeZone.getAvailableIDs();
Collections.addAll(clocks, ids);
这个 ArrayList 稍后用于使用我的自定义 BaseAdapter 填充列表视图。有一些条目不是特别有用,我不希望它们出现在列表中,例如:
Etc/GMT+10
PST8PDT
NZ-CHAT
我添加了一个 for 循环来遍历所有条目并删除任何不需要的条目,目前我有以下检查用于测试目的:
String string = clocks.get(i);
String[] split = string.split("/");
if(string.equals("MST7MDT")) {
clocks.remove(i);
}
if(string.contains("Etc/")) {
clocks.remove(i);
}
if(split.length <= 1) {
clocks.remove(i);
}
if(!string.contains("/")) {
clocks.remove(i);
}
现在这应该删除与"MST7MDT"相同的一个(它没有),任何包含"Etc/"的元素(只有大约一半的Etc/example
元素被删除),以及任何不包含"/"拆分的元素都应该做同样的事情(不是全部被删除)。我已经用trim()
试过了,但没有帮助。这似乎不是remove(int)
的问题,我也尝试传递对象,但仍然一无所获。
任何帮助将不胜感激,是否有其他人遇到过TimeZone.getAvailableIDs()
结果的问题?我在这里错过了什么愚蠢的东西吗?
保留区域,而不是丢弃
正如我们在维基百科上的时区名称列表中看到的那样,这些时区多年来一直在变化和发展。许多条目只是其他区域的别名。有些被证明是另一个区域的无意副本。许多是考虑不周的,现在已被弃用。
我建议不要关注要删除的区域,而是关注要保留的区域。本答案的其余部分说明了如何操作。
TimeZone.getAvailableIDs()
TimeZone
班几年前被java.time.ZoneId
班取代。永远不要使用可怕的传统日期时间类,如TimeZone
、Date
和Calendar
。
大洲列表
作为获取清理列表的第一步,我建议过滤那些以这些大陆之一开头的名称:
- 欧洲
- 非洲
- 南极洲
- 大西洋
- 美洲
- 太平洋
- 印度
- 澳大利亚
并添加一个条目 Etc/UTC
当用户根本不想要时区时。
在 Java 代码中,按字母顺序排序。
List < String > zoneGroupNames = List.of(
"Africa" ,
"Antarctica" ,
"Atlantic" ,
"America" ,
"Australia" ,
"Europe" ,
"Indian" ,
"Pacific" ,
"UTC"
);
我建议你为用户提供一个两步过程,他们首先建议一个大陆,然后是一个区域。
区域组名称到区域名称的多重映射
生成每个区域组名称的Map
,以收集区域 ID 名称。我们需要一个组名的映射,例如 Europe
到区域名称列表,例如 Europe/Berlin
、 Europe/London
和 Europe/Malta
。
Map < String, List < String > > mapGroupNameToZoneNames = new TreeMap <>();
将键映射到值集合称为"多重映射"。我们现在具有内置的多重映射功能,其中包含与 Java 捆绑在一起的Map
实现。致电Map::computeIfAbsent
(请参阅此答案)。
Set < String > zoneIdStrings = ZoneId.getAvailableZoneIds();
for ( String zoneIdString : zoneIdStrings )
{
String groupName = zoneIdString.split( "/" )[ 0 ];
if ( zoneGroupNames.contains( groupName ) )
{
mapGroupNameToZoneNames.computeIfAbsent( groupName , ( x -> new ArrayList <>() ) ).add( zoneIdString );
} // Else skip it.
}
System.out.println( "mapGroupNameToZoneNames = " + mapGroupNameToZoneNames );
为Etc/UTC
添加一个条目。
mapGroupNameToZoneNames.computeIfAbsent( "Etc" , ( x -> new ArrayList <>() ) ).add( "UTC" );
向用户演示
向用户显示该组列表。假设用户选择项目 #6(索引 5),该项目当前Europe
。
String groupNameChosenByUser = zoneGroupNames.get( 5 ); // Europe
List < String > zoneNamesOfGroup = mapGroupNameToZoneNames.get( groupNameChosenByUser );
显示该组的区域名称列表。假设用户选择项目 #12(索引 11),该项目当前Europe/Malta
。
String zoneNameChosenByUser = zoneNamesOfGroup.get( 11 ); // Malta
从该区域名称的字符串创建一个ZoneId
对象。
ZoneId zoneIdChosenByUser = ZoneId.of( zoneNameChosenByUser );
<小时 />zoneIdChosenByUser.toString() = Europe/Malta
关于 java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧旧日期时间类,如java.util.Date
、Calendar
和SimpleDateFormat
。
要了解更多信息,请参阅 Oracle 教程。并搜索堆栈溢出以获取许多示例和解释。规范为 JSR 310。
Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。
您可以直接与数据库交换java.time对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要java.sql.*
类。
从哪里获得java.time类?
- Java SE 8、Java SE 9、Java SE
- 10、Java SE 11 及更高版本 - 标准 Java API 的一部分,具有捆绑实现。
- Java 9添加了一些小功能和修复。 Java SE
- 6 和 Java SE 7
- 大多数java.time功能在ThreeTen-Backport中向后移植到Java 6和7。
- 人造人
- java.time 类的 Android 捆绑包实现的更高版本。
- 对于早期的Android(<26),ThreeTenABP项目适应了ThreeTen-Backport(如上所述)。请参阅如何使用ThreeTenABP...。