Android TimeZone.getAvailableIDs()产生奇怪的字符串 [英] Android TimeZone.getAvailableIDs() producing strange strings

查看:191
本文介绍了Android TimeZone.getAvailableIDs()产生奇怪的字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用TimeZone.getAvailableIDs()提取所有可用时区ID字符串的Android应用程序.这些ID按照以下内容保存到ArrayList:

I have an Android application which uses TimeZone.getAvailableIDs() to pull all available timezone ID strings. These IDs are saved to an ArrayList, as per the following:

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

此ArrayList稍后用于使用我的自定义BaseAdapter填充ListView.有些条目不是特别有用,我不希望它们出现在列表中,例如:

This ArrayList is used later on to populate a ListView using my custom BaseAdapter. There are a few entries that aren't particularly informative and I don't want them in the list, such as:

Etc/GMT+10
PST8PDT
NZ-CHAT

我添加了一个for循环以遍历所有条目,并删除所有不需要的条目,目前我出于测试目的进行了以下检查:

I added a for loop to go through all entries and remove any unwanted ones, at the moment I have the following checks for testing purposes:

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)似乎没有问题,我也尝试传递对象,但仍然没有.

Now this should delete the one identical to "MST7MDT" (it doesn't), any containing "Etc/" (only about half of the Etc/example elements get deleted), and any that don't contain a "/" the split one should do the same (not all are deleted). I've tried it with trim() but it hasn't helped. It doesn't seem to be a problem with remove(int), I tried passing the Object too but still nothing.

任何帮助将不胜感激,TimeZone.getAvailableIDs()的结果是否有其他人遇到问题?我在这里想念一些愚蠢的东西吗?

Any help would be much appreciated, has anyone else experienced problems with the results from TimeZone.getAvailableIDs()? Am I missing something stupid here?

推荐答案

保留区域,而不是丢弃

正如我们在时区名称列表上看到的,多年来发生了变化和发展.许多条目仅仅是其他区域的别名.许多人构思不当,现已弃用.

Keep zones, rather than discard

As we can see in the list of time zone names on Wikipedia, the zones have changed and evolved over the years. Many of the entries are mere alias for other zones. And many were ill-conceived and are now deprecated.

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

I suggest that rather than focusing on zones to delete, you focus on zones to keep. The rest of this Answer shows how.

TimeZone.getAvailableIDs()

TimeZone类是几年前被java.time.ZoneId类取代的.切勿使用可怕的旧式日期时间区域,例如TimeZoneDateCalendar.

The TimeZone class was years ago supplanted by the java.time.ZoneId class. Never use the terrible legacy date-time zones such as TimeZone, Date, and Calendar.

作为获取清理清单的第一步,我建议过滤以以下大洲之一开头的名称:

As a first step in getting a cleaned-up list, I suggest filtering for those names that begin with one of these continents:

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

并在用户根本不需要时区时添加Etc/UTC条目.

And add an entry of Etc/UTC for when the user wants no time zone at all.

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

In Java code, sorted alphabetically.

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

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

I suggest you offer a two-step process for the user, where they suggest first a continent, then a zone.

构建 Map 到区域ID名称的集合.我们需要一个组名称(例如Europe)到区域名称列表(例如Europe/BerlinEurope/LondonEurope/Malta)的映射.

Build a Map of each zone group name to collection of zone id names. We need a map of the group name such as Europe to a list of the zone names such as Europe/Berlin, Europe/London, and Europe/Malta.

Map < String, List < String > > mapGroupNameToZoneNames = new TreeMap <>();

将键映射到值的集合称为多图".现在,我们具有内置的多图功能,并且Java捆绑了Map实现.调用 Map::computeIfAbsent (请参阅此答案).

Mapping a key to a collection of values is known as a "multimap". We now have built-in multimap functionality with the Map implementations bundled with Java. Call Map::computeIfAbsent (see 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" );

呈现给用户

向用户呈现该组列表.假设用户选择了当前为Europe的项目#6(索引5).

Present to user

Present that list of groups to the user. Say the user selects item # 6 (index 5), which is currently Europe.

String groupNameChosenByUser = zoneGroupNames.get( 5 ); // Europe
List < String > zoneNamesOfGroup = mapGroupNameToZoneNames.get( groupNameChosenByUser );

显示该组的区域名称列表.假设用户选择了当前为Europe/Malta的项目#12(索引11).

Present that list of zone names for that one group. Say the user selects item # 12 (index 11), which is currently Europe/Malta.

String zoneNameChosenByUser = zoneNamesOfGroup.get( 11 );  // Malta

从该区域名称的字符串中创建一个ZoneId对象.

Make a ZoneId object from the string of that zone name.

ZoneId zoneIdChosenByUser = ZoneId.of( zoneNameChosenByUser );

zoneIdChosenByUser.toString()=欧洲/马耳他

zoneIdChosenByUser.toString() = Europe/Malta


关于 java.time

旧版日期时间类,例如 Calendar ,& SimpleDateFormat .


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

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

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Joda-Time 项目,现在位于<一个href ="https://en.wikipedia.org/wiki/Maintenance_mode" rel ="nofollow noreferrer">维护模式,建议迁移到您可以直接与数据库交换 java.time 对象.使用符合 JDBC驱动程序/jeps/170"rel =" nofollow noreferrer> JDBC 4.2 或更高版本.不需要字符串,不需要java.sql.*类.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

在哪里获取java.time类?

Where to obtain the java.time classes?

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆