Android TimeZone.getAvailableIDs() 生成奇怪的字符串



我有一个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班取代。永远不要使用可怕的传统日期时间类,如TimeZoneDateCalendar

大洲列表

作为获取清理列表的第一步,我建议过滤那些以这些大陆之一开头的名称:

  • 欧洲
  • 非洲
  • 南极洲
  • 大西洋
  • 美洲
  • 太平洋
  • 印度
  • 澳大利亚

并添加一个条目 Etc/UTC 当用户根本不想要时区时。

在 Java 代码中,按字母顺序排序。

List < String > zoneGroupNames = List.of(
        "Africa" ,
        "Antarctica" ,
        "Atlantic" ,
        "America" ,
        "Australia" ,
        "Europe" ,
        "Indian" ,
        "Pacific" ,
        "UTC"
);

我建议你为用户提供一个两步过程,他们首先建议一个大陆,然后是一个区域。

区域

组名称到区域名称的多重映射

生成每个区域组名称的Map,以收集区域 ID 名称。我们需要一个组名的映射,例如 Europe 到区域名称列表,例如 Europe/BerlinEurope/LondonEurope/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.DateCalendarSimpleDateFormat

要了解更多信息,请参阅 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
  • 6Java SE 7
  • 大多数java.time功能在ThreeTen-Backport中向后移植到Java 6和7。
  • 人造人
  • java.time 类的 Android 捆绑包实现的更高版本。
  • 对于早期的Android(<26),ThreeTenABP项目适应了ThreeTen-Backport(如上所述)。请参阅如何使用ThreeTenABP...

相关内容

  • 没有找到相关文章

最新更新