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

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

问题描述

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

ArrayList时钟 = 新的 ArrayList<>();String[] ids = TimeZone.getAvailableIDs();Collections.addAll(clocks, ids);

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

Etc/GMT+10PST8PDT新西兰聊天

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

String string = clocks.get(i);String[] split = string.split("/");if(string.equals("MST7MDT")) {时钟.remove(i);}if(string.contains("Etc/")) {时钟.remove(i);}if(split.length <= 1) {时钟.remove(i);}if(!string.contains("/")) {时钟.remove(i);}

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

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

解决方案

保留区域,而不是丢弃

正如我们在 维基百科上的时区名称列表中所见,这些区域有多年来发生了变化和发展.许多条目只是其他区域的别名.很多人都考虑不周,现在已被弃用.

我建议您不要关注要删除的区域,而是关注要保留的区域.这个答案的其余部分展示了如何.

<块引用>

TimeZone.getAvailableIDs()

TimeZone 类在多年前被 java.time.ZoneId 类取代.永远不要使用糟糕的旧日期时区,例如 TimeZoneDateCalendar.

大陆列表

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

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

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

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

列表<字符串 >zoneGroupNames = List.of(非洲",南极",大西洋",美国" ,澳大利亚" ,欧洲" ,印度",太平洋",世界标准时间");

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

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

构建Map 每个区域组名称到区域 ID 名称的集合.我们需要将组名称(例如 Europe)映射到区域名称列表(例如 Europe/BerlinEurope/London,以及欧洲/马耳他.

地图 <字符串,列表 <字符串 >>mapGroupNameToZoneNames = new TreeMap <>();

将键映射到值集合称为多映射".我们现在有内置的 multimap 功能和 Java 捆绑的 Map 实现.调用 Map::computeIfAbsent(参见这个答案).

设置<字符串 >zoneIdStrings = ZoneId.getAvailableZoneIds();for ( String zoneIdString : zoneIdStrings ){String groupName = zoneIdString.split( "/" )[ 0 ];if ( zoneGroupNames.contains( groupName ) ){mapGroupNameToZoneNames.computeIfAbsent( groupName , ( x -> new ArrayList <>() ) ).add( zoneIdString );}//否则跳过它.}System.out.println( "mapGroupNameToZoneNames = " + mapGroupNameToZoneNames );

Etc/UTC 添加该条目.

mapGroupNameToZoneNames.computeIfAbsent( "Etc" , ( x -> new ArrayList <>() ) ).add( "UTC" );

呈现给用户

向用户展示该组列表.假设用户选择了当前 Europe 的第 6 项(索引 5).

String groupNameChosenByUser = zoneGroupNames.get( 5 );//欧洲列表<字符串 >zoneNamesOfGroup = mapGroupNameToZoneNames.get( groupNameChosenByUser );

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

String zoneNameChosenByUser = zoneNamesOfGroup.get( 11 );//马耳他

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

ZoneId zoneIdChosenByUser = ZoneId.of( zoneNameChosenByUser );

<块引用>

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

<小时>

关于java.time

java.time 框架内置于 Java 8 及更高版本中.这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date, 日历, &SimpleDateFormat.

要了解更多信息,请参阅 Oracle 教程.并在 Stack Overflow 上搜索许多示例和解释.规范是 JSR 310.

Joda-Time 项目,现在在 维护模式,建议迁移到 java.time 类.

您可以直接与您的数据库交换 java.time 对象.使用符合 JDBC 驱动程序/jeps/170" rel="nofollow noreferrer">JDBC 4.2 或更高版本.不需要字符串,不需要 java.sql.* 类.

从哪里获取 java.time 类?

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

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

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

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.

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()

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.

List of continents

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

  • Europe
  • Africa
  • Antarctica
  • Atlantic
  • America
  • Pacific
  • Indian
  • Australia

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

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.

Multimap of zone group name to zone names

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

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

Add that one entry for Etc/UTC.

mapGroupNameToZoneNames.computeIfAbsent( "Etc" , ( x -> new ArrayList <>() ) ).add( "UTC" );

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

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

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

ZoneId zoneIdChosenByUser = ZoneId.of( zoneNameChosenByUser );

zoneIdChosenByUser.toString() = Europe/Malta


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.

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

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

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.

Where to obtain the java.time classes?

这篇关于Android TimeZone.getAvailableIDs() 产生奇怪的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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