我想在 API 23 上以 UTC 格式显示时区的完整列表



>我需要显示一个自定义活动,其中包含一个列表视图,按照以下格式显示所有时区:

ZoneID   (UTC <+/-> hh:mm)

应对这些时区进行排序(类似于 Windows 中显示的时区设置),以便:

  1. 首先显示所有 UTC 负时区
  2. 接下来显示所有 UTC+00:00 时区
  3. 所有大于 UTC+00:00 的时区最后显示

我遇到了很多例子,但它们都在ZoneId类中使用JDK 1.8(Android API级别26)。 这里和这里很少解释这样的例子。

我想要一些替代这些示例的方法,我可以在Android API Level 23或JDK 1.7中使用。

预期输出:

America/Thule (UTC-03:00)
America/Argentina/La_Rioja (UTC-03:00)
America/Belem (UTC-03:00)
America/Jujuy (UTC-03:00)
America/Bahia (UTC-03:00)
America/Goose_Bay (UTC-03:00)
America/Argentina/San_Juan (UTC-03:00)
America/Argentina/ComodRivadavia (UTC-03:00)
America/Argentina/Tucuman (UTC-03:00)
America/Rosario (UTC-03:00)
SystemV/AST4ADT (UTC-03:00)
America/Argentina/Buenos_Aires (UTC-03:00)
America/St_Johns (UTC-02:30)
Canada/Newfoundland (UTC-02:30)
America/Miquelon (UTC-02:00)
Etc/GMT+2 (UTC-02:00)
America/Godthab (UTC-02:00)
America/Noronha (UTC-02:00)
Brazil/DeNoronha (UTC-02:00)
Atlantic/South_Georgia (UTC-02:00)
Etc/GMT+1 (UTC-01:00)
Atlantic/Cape_Verde (UTC-01:00)
Africa/Dakar (UTC+00:00) 
Africa/Bissau (UTC+00:00) 
WET (UTC+00:00) 
Etc/Greenwich (UTC+00:00) 
Africa/Timbuktu (UTC+00:00) 
Africa/Monrovia (UTC+00:00) 
Europe/Bratislava (UTC+01:00) 
Arctic/Longyearbyen (UTC+01:00) 
Europe/Vatican (UTC+01:00) 
Europe/Monaco (UTC+01:00) 
Africa/Harare (UTC+02:00) 
Europe/Tallinn (UTC+02:00) 

使用java.util.TimeZone列表并按偏移量对它们进行排序:

String[] ids = TimeZone.getAvailableIDs();
List<TimeZone> zones = new ArrayList<>();
for (String id : ids) {
zones.add(TimeZone.getTimeZone(id));
}
Collections.sort(zones, new Comparator<TimeZone>() {
// compare by the offset, reverse order
@Override
public int compare(TimeZone o1, TimeZone o2) {
return o1.getRawOffset() - o2.getRawOffset();
}});

然后打印此列表,使用 ID 和帮助程序方法来设置偏移量的格式:

public String formatOffset(int rawOffset) {
StringBuilder sb = new StringBuilder("UTC").append(rawOffset < 0 ? "-" : "+");
int secs = Math.abs(rawOffset) / 1000;
int hours = secs / 3600;
secs -= hours * 3600;
int mins = secs / 60;
sb.append(hours < 10 ? "0" : "").append(hours).append(":");
sb.append(mins < 10 ? "0" : "").append(mins);
return sb.toString();
}
for (TimeZone tz : zones) {
System.out.println(tz.getID() + " (" + formatOffset(tz.getRawOffset()) + ")");
}

输出将如下所示:

Etc/GMT+12 (UTC-12:00)
Etc/GMT+11 (UTC-11:00)
Pacific/Midway (UTC-11:00)
Pacific/Niue (UTC-11:00)
... lots of timezones

请注意,我没有包含"漂亮的选项卡"格式,这取决于您。

我还使用了getRawOffset,它返回该区域的当前偏移量 - 检查 javadoc:https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html#getRawOffset()

此方法不考虑夏令时更改或任何其他历史数据(例如过去使用不同偏移量的国家/地区 - 相信我,大多数国家/地区(如果不是全部国家/地区)在其历史记录中至少有一个偏移量更改)。要使用这些其他偏移量,您可以使用getOffset方法,将引用日期/时间戳作为参数传递 - 有关详细信息,请查看 javadoc。

我还使用了getAvailableIDs,它返回所有时区,但您可以过滤此列表以仅包含所需的区域。


但老实说,这个旧的API(java.utilDateCalendarSimpleDateFormatTimeZone等)真的很糟糕,有很多缺陷和烦人的错误,没有人值得再使用它们了。特别是今天,我们有更好的API。

在没有java.time类(例如ZoneId)的 API 级别中,您可以使用 ThreeTen 向后移植,如另一个答案中所述。然后,您可以按照找到的示例进行操作。

一个主要区别是,此 API 始终需要Instant作为参考来获取偏移量 - 因为它会检查所有时区的历史数据,以了解在特定时刻使用的偏移量是多少(在下面的代码中,我使用的是当前时刻):

Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
List<ZoneId> timezones = new ArrayList<>();
for (String id : availableZoneIds) {
timezones.add(ZoneId.of(id));
}
// current instant
final Instant now = Instant.now();
Collections.sort(timezones, new Comparator<ZoneId>() {
// compare by offset in reverse order, use the Instant as a reference
@Override
public int compare(ZoneId o1, ZoneId o2) {
return o2.getRules().getOffset(now).compareTo(o1.getRules().getOffset(now));
}
});
for (ZoneId zone : timezones) {
ZoneOffset offset = zone.getRules().getOffset(now);
System.out.println(zone + " (UTC" + (offset.getTotalSeconds() == 0 ? "+00:00" : offset.toString()) + ")");
}

另请注意,ZoneOffset类有一个很好的toString()方法,该方法已经以正确的格式打印偏移量(除非它是零,它打印为Z,但这并不难修复)。

作为另一个答案的补充,您可以使用格式化程序打印区域和偏移量:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("VV '(UTC'xxx')'");
for (ZoneId zone : timezones) {
System.out.println(fmt.format(now.atZone(zone)));
}

它产生相同的输出:"VV"打印区域 ID,"xxx"打印偏移量。

只需获取 ThreeTenABP 并将其添加到您的 Android 项目中,即可使用 java.time 中的ZoneId和其他好东西,java.time 是 Java 8 中出现的现代 Java 日期和时间 API,也被向后移植到 Java 6 和 7。

链接

  • Java 规范请求 (JSR) 310,其中首次描述了java.time
  • ThreeTen Backport项目,将java.time向后移植到Java 6和7(JSR-310的ThreeTen)。
  • ThreeTenABP,ThreeTen Backport 的安卓版
  • 问:如何在Android项目中使用ThreeTenABP,并进行了非常详尽的解释。

使用 Joda-Time 的解决方案:

首先使用 DateTimeZone 类获取所有 ID,然后使用 DateTimeZone.getOffset(Instant) 方法对它们进行排序。DateTimeZone 考虑夏令时与 java.util 提供的 TimeZone.getrawOffset() 不同。

Set<String> availableIDs = DateTimeZone.getAvailableIDs();
List<DateTimeZone> dateTimezones = new ArrayList<>();
for (String id : availableIDs) {
dateTimezones.add(DateTimeZone.forID(id));
}
final Instant now = Instant.now();
Collections.sort(dateTimezones, new Comparator<DateTimeZone>() {
@Override
public int compare(DateTimeZone o1, DateTimeZone o2) {
return o1.getOffset(now)-o2.getOffset(now);
}
});
for (DateTimeZone dateTimeZone : dateTimezones) {
int offset = dateTimeZone.getOffset(now);
String out = String.format("%35s %s%n", dateTimeZone, " (" + formatOffset(offset) + ")");
System.out.printf(out);
}

formatOffset(int) 从上面的例子中重用。

链接:

链接到下载乔达时间

相关内容

  • 没有找到相关文章

最新更新