作为@Ole V.V.'s answer的补充,我发现了另一种使用ThreeTenABP的方法,但不需要正则表达式替换(尽管我不认为它更简单,下面更多)。
使用DateTimeFormatterBuilder
可以使用HashMap
将偏移值映射到String
。因此,对于整个抵消时间(如+03:00
),可以将相应的值映射到字符串+3
等等。
唯一的问题是,ZoneOffset
有秒精度。最小值和最大值分别为UTC-18:00:00
和UTC+18:00:00
。所以所有可能的值是UTC-18:00:00
,UTC-17:59:59
,UTC-17:59:58
等等。格式化程序需要映射所有可能的值(否则它将显示偏移量的秒数值),因此地图将会有超过120K个条目!
为了建立这个地图,我做了2个循环:
- 第一个循环映射整个小时的偏移量(
+01:00
至+1
,-02:00
到-2
等)
- 第二个循环的所有映射其它值(它们保持不变):
- 整个小时> = 10(如
+10:00
)
- 未整小时(如
+05:30
)
的代码来创建格式化:
// builds a hashmap to map all offset values
Map<Long, String> map = new HashMap<>();
// First loop: Map whole hours from 1 to 9 and from -9 to -1
// So a "+01:00" offset is displayed as "+1"
for (int i = 1; i <= 9; i++) {
long seconds = ZoneOffset.ofHours(i).getTotalSeconds();
// 1 hour offset maps to "+1" and so on
map.put(seconds, "+" + i);
// -1 hour offset maps to "-1" and so on
map.put(-seconds, "-" + i);
}
// second loop: Need to map all other possible values for not-whole hours
// offsets like "+10:00" and "+01:30" are not changed
int minOffset = ZoneOffset.MIN.getTotalSeconds();
int maxOffset = ZoneOffset.MAX.getTotalSeconds();
for (long i = minOffset; i <= maxOffset; i++) {
// the map already contains whole hours, don't need to overwrite the values
if (!map.containsKey(i)) {
// uses default String representation (like "+05:30")
map.put(i, ZoneOffset.ofTotalSeconds((int) i).getId());
}
}
// create the formatter
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// year/month/day and the "|"
.appendPattern("uuuu/MM/dd | ")
// use the map of custom values (offset will use the values in the map)
.appendText(ChronoField.OFFSET_SECONDS, map)
// create formatter
.toFormatter();
一些测试:
LocalDateTime dt = LocalDateTime.of(2017, 5, 1, 10, 0);
ZonedDateTime z = ZonedDateTime.of(dt, ZoneId.of("America/Sao_Paulo")); // UTC-03:00
System.out.println(formatter.format(z)); // 2017/05/01 | -3
// just picking some timezone in Arabia Stardard Time
// (there are more than one timezone in AST: https://en.wikipedia.org/wiki/UTC%2B03:00#Arabia_Standard_Time)
// I don't know in which one you are
z = ZonedDateTime.of(dt, ZoneId.of("Asia/Qatar")); // UTC+03:00
System.out.println(formatter.format(z)); // 2017/05/01 | +3
// 2-digit offset
z = ZonedDateTime.of(dt, ZoneId.of("Asia/Vladivostok")); // UTC+10:00
System.out.println(formatter.format(z)); // 2017/05/01 | +10:00
// not whole hour
z = ZonedDateTime.of(dt, ZoneId.of("Asia/Kathmandu")); // UTC+05:45
System.out.println(formatter.format(z)); // 2017/05/01 | +05:45
的输出是:
2017年5月1日| -3
2017/05/01 | +3
2017/05/01 | +10:00
2017/05/01 | +05:45
注:
如果偏移量不是整小时数,您希望发生什么? –
@ OleV.V。没有得到什么意思呢? –
例如,假设“Asia/Kathmandu”的区域偏移量为+05:45。这应该如何打印?如果答案是“不关心”,我建议你在这种情况下抛出异常。 –