作爲@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。這應該如何打印?如果答案是「不關心」,我建議你在這種情況下拋出異常。 –