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

时间:2015-01-14 17:46:44

标签: java android arraylist timezone baseadapter

我有一个Android应用程序,它使用TimeZone.getAvailableIDs()来提取所有可用的时区ID字符串。这些ID将保存到ArrayList,具体如下:

ArrayList<String> clocks = new ArrayList<>();
String[] ids = TimeZone.getAvailableIDs();
Collections.addAll(clocks, ids);

稍后将使用此ArrayList使用我的自定义BaseAdapter填充ListView。有一些条目不具备特别的信息,我不希望它们出现在列表中,例如:

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);
}

现在这应该删除与&#34; MST7MDT&#34;相同的那个。 (它没有),任何含有&#34; Etc /&#34; (只有大约一半的Etc/example元素被删除),任何不包含&#34; /&#34;拆分应该做同样的事情(并非所有都被删除)。我已经用trim()尝试了它,但它没有帮助。它似乎不是remove(int)的问题,我尝试传递对象但仍然没有。

我们非常感谢任何帮助,其他人是否遇到过TimeZone.getAvailableIDs()结果的问题?我在这里错过了一些愚蠢的东西吗?

1 个答案:

答案 0 :(得分:2)

保留区域,而不是丢弃

我们在list of time zone names on Wikipedia中看到,这些年来,这些区域已经发生了变化和演变。许多条目仅仅是其他区域的别名。许多人构思不当,现已弃用。

我建议您不要关注要删除的区域,而要关注要保留的区域。此答案的其余部分说明了如何。

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(请参阅this Answer)。

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()=欧洲/马耳他


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规范为JSR 310

Joda-Time项目(现在位于maintenance mode中)建议迁移到java.time类。

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?