将时区转换为 Java 11 中的 GMT 值
Converting Time Zone to GMT values in Java 11
我们在配置 table 中保留城市的时区,使用 时区 ID 值作为 Europe/London
、Asia/Tokyo
等. 但是,当从列表中选择时区时,用户需要查看这些时区的 GMT 值,我们希望将 Display Name of Time Zone Options 显示为 (UTC+00:00) Dublin, Edinburgh, Lisbon, London
而不是比 Europe/London
。正如我们所知,GMT 值不是固定的,我们应该进行一些转换才能显示当前时区显示值。那么,我怎样才能在 Java 中做到这一点?
如果return您需要什么,您可以查看下面的代码:
public class Whosebug {
public static void main(String[] args) {
List<String> gmt = getTimeZoneList(OffsetBase.GMT);
gmt.forEach(System.out::println);
}
public static List<String> getTimeZoneList(OffsetBase base) {
LocalDateTime now = LocalDateTime.now();
return ZoneId.getAvailableZoneIds().stream()
.map(ZoneId::of)
.sorted(new ZoneComparator())
.map(id -> String.format(
"(%s%s) %s",
base, getOffset(now, id), id.getId()))
.collect(Collectors.toList());
}
private static String getOffset(LocalDateTime dateTime, ZoneId id) {
return dateTime
.atZone(id)
.getOffset()
.getId()
.replace("Z", "+00:00");
}
private static class ZoneComparator implements Comparator<ZoneId> {
@Override
public int compare(ZoneId zoneId1, ZoneId zoneId2) {
LocalDateTime now = LocalDateTime.now();
ZoneOffset offset1 = now.atZone(zoneId1).getOffset();
ZoneOffset offset2 = now.atZone(zoneId2).getOffset();
return offset1.compareTo(offset2);
}
}
enum OffsetBase {
GMT, UTC
}
}
结果如下:
(GMT+14:00) Pacific/Apia
(GMT+14:00) Pacific/Kiritimati
(GMT+14:00) Etc/GMT-14
这只是示例,因为列表很长
更新
基于请求者,因此要获取特定区域 ID 的 GMT。
public static List<String> getTimeZoneList(OffsetBase base, String wantedZoneId) {
LocalDateTime now = LocalDateTime.now();
return ZoneId.getAvailableZoneIds().stream()
.map(ZoneId::of)
.sorted(new ZoneComparator())
.filter(zoneId -> zoneId.getId().equals(wantedZoneId))
.map(id -> String.format(
"(%s%s) %s",
base, getOffset(now, id), id.getId()))
.collect(Collectors.toList());
}
这个功能是一样的,只是加上[过滤]功能
比方说,您的 ID 在 Set<String>
中,就像 ZoneId.getAvailableZoneIds()
.
您可以使用 ZoneId
来及时创建当前时刻并根据需要格式化其偏移量:
public static void main(String[] args) throws IOException {
// provide two formatters for the desired outputs GMT... and UTC...
DateTimeFormatter gmtFormatter = DateTimeFormatter.ofPattern("OOOO");
DateTimeFormatter utcFormatter = DateTimeFormatter.ofPattern("'UTC'xxx");
// stream all the IDs (sorted) and create a ZonedDateTime at each ZoneId
ZoneId.getAvailableZoneIds().stream().sorted().forEach(zoneId -> {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of(zoneId));
// then print the zone id and the other representations using the formatters
System.out.println(
String.format("%-32s %9s / %9s",
zoneId.toString(),
now.format(gmtFormatter),
now.format(utcFormatter)
));
});
}
第一个格式化程序只考虑 GMT+/-HH:mm 表示中的区域,第二个只考虑文字 UTC 加上偏移量为 +/-HH:mm.
(缩短!)输出是
Africa/Abidjan GMT / UTC+00:00
Africa/Accra GMT / UTC+00:00
Africa/Addis_Ababa GMT+03:00 / UTC+03:00
Africa/Algiers GMT+01:00 / UTC+01:00
Africa/Asmara GMT+03:00 / UTC+03:00
Africa/Asmera GMT+03:00 / UTC+03:00
Africa/Bamako GMT / UTC+00:00
...
US/Alaska GMT-09:00 / UTC-09:00
US/Aleutian GMT-10:00 / UTC-10:00
US/Arizona GMT-07:00 / UTC-07:00
US/Central GMT-06:00 / UTC-06:00
US/East-Indiana GMT-05:00 / UTC-05:00
US/Eastern GMT-05:00 / UTC-05:00
US/Hawaii GMT-10:00 / UTC-10:00
US/Indiana-Starke GMT-06:00 / UTC-06:00
US/Michigan GMT-05:00 / UTC-05:00
US/Mountain GMT-07:00 / UTC-07:00
US/Pacific GMT-08:00 / UTC-08:00
US/Samoa GMT-11:00 / UTC-11:00
UTC GMT / UTC+00:00
Universal GMT / UTC+00:00
W-SU GMT+03:00 / UTC+03:00
WET GMT / UTC+00:00
Zulu GMT / UTC+00:00
这是您的其他要求的想法,列出每个偏移量的城市:
public static void main(String[] args) throws IOException {
// provide two formatters for the desired outputs GMT... and UTC...
DateTimeFormatter gmtFormatter = DateTimeFormatter.ofPattern("OOOO");
DateTimeFormatter utcFormatter = DateTimeFormatter.ofPattern("'UTC'xxx");
// get a map of zones grouped by offset
Map<ZoneId, List<ZoneId>> zonesPerOffset =
ZoneId.getAvailableZoneIds().stream()
.map(ZoneId::of)
.collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(zoneId -> ZonedDateTime.now(zoneId).getOffset()));
// print them
zonesPerOffset.forEach((offset, zones) -> {
String o = ZonedDateTime.now(zones.get(0)).format(utcFormatter);
String zs = String.join(", ", zones.stream().map(zone -> {
String[] idParts = zone.getId().split("/");
return idParts[idParts.length - 1];
}).collect(Collectors.toList()));
String out = String.format("(%9s) %s", o, zs);
System.out.println(out);
});
}
输出(缩短):
(UTC+04:00) Yerevan, GMT-4, Dubai, Reunion, Mauritius, Saratov, Samara, Mahe, Baku, Muscat, Volgograd, Astrakhan, Tbilisi, Ulyanovsk
(UTC+00:00) London, GMT, GMT-0, Jersey, St_Helena, Guernsey, Isle_of_Man, GMT+0, Banjul, GMT, Freetown, GB-Eire, Bamako, GB, Conakry, Portugal, Universal, Sao_Tome, Nouakchott, Troll, UTC, Universal, Faeroe, Abidjan, Eire, Accra, Faroe, UCT, GMT0, Dublin, Zulu, Ouagadougou, Reykjavik, Madeira, Zulu, Iceland, Lisbon, Canary, Lome, Greenwich, Belfast, GMT0, Danmarkshavn, Dakar, Bissau, WET, Greenwich, Timbuktu, UCT, Monrovia, UTC
(UTC+08:00) Kuching, Chungking, GMT-8, Perth, Macao, Macau, Choibalsan, Shanghai, Ulan_Bator, Chongqing, Ulaanbaatar, Taipei, Manila, PRC, Ujung_Pandang, Harbin, Singapore, Brunei, West, Hong_Kong, Makassar, Hongkong, Kuala_Lumpur, Irkutsk, Singapore
(UTC+12:00) Kwajalein, Wallis, Funafuti, Nauru, Kwajalein, Wake, Norfolk, Tarawa, Kamchatka, GMT-12, Anadyr, Majuro
这样看起来不太好,但您可以根据需要应用过滤器。也许删除前导 UTC 等的元素,也许过滤掉特定的大陆,等等。
作为方法:
public static ZoneOffset getOffsetOf(ZoneId zoneId) {
return ZonedDateTime.now(zoneId).getOffset();
}
// this one may throw an Exception if you pass an invalid zoneId as String!
public static ZoneOffset getOffsetOf(String zoneId) {
return ZonedDateTime.now(ZoneId.of(zoneId)).getOffset();
}
public static List<ZoneId> getAllZoneIdsWith(ZoneOffset zoneOffset) {
return ZoneId.getAvailableZoneIds()
.stream()
.filter(zoneId -> ZonedDateTime.now(ZoneId.of(zoneId))
.getOffset().equals(zoneOffset))
.map(ZoneId::of)
.collect(Collectors.toList());
}
public static String getGmtFormat(ZoneId zoneId) {
return String.format("(%s) %s",
ZonedDateTime.now(zoneId)
.format(DateTimeFormatter.ofPattern("OOOO")),
zoneId.getId());
}
使用最后一种方法获取所有可用 ZoneId
s 的 GMT 格式:
List<String> gmtFormats = ZoneId.getAvailableZoneIds()
.stream()
.map(zone -> getGmtFormat(ZoneId.of(zone)))
.collect(Collectors.toList());
我们在配置 table 中保留城市的时区,使用 时区 ID 值作为 Europe/London
、Asia/Tokyo
等. 但是,当从列表中选择时区时,用户需要查看这些时区的 GMT 值,我们希望将 Display Name of Time Zone Options 显示为 (UTC+00:00) Dublin, Edinburgh, Lisbon, London
而不是比 Europe/London
。正如我们所知,GMT 值不是固定的,我们应该进行一些转换才能显示当前时区显示值。那么,我怎样才能在 Java 中做到这一点?
如果return您需要什么,您可以查看下面的代码:
public class Whosebug {
public static void main(String[] args) {
List<String> gmt = getTimeZoneList(OffsetBase.GMT);
gmt.forEach(System.out::println);
}
public static List<String> getTimeZoneList(OffsetBase base) {
LocalDateTime now = LocalDateTime.now();
return ZoneId.getAvailableZoneIds().stream()
.map(ZoneId::of)
.sorted(new ZoneComparator())
.map(id -> String.format(
"(%s%s) %s",
base, getOffset(now, id), id.getId()))
.collect(Collectors.toList());
}
private static String getOffset(LocalDateTime dateTime, ZoneId id) {
return dateTime
.atZone(id)
.getOffset()
.getId()
.replace("Z", "+00:00");
}
private static class ZoneComparator implements Comparator<ZoneId> {
@Override
public int compare(ZoneId zoneId1, ZoneId zoneId2) {
LocalDateTime now = LocalDateTime.now();
ZoneOffset offset1 = now.atZone(zoneId1).getOffset();
ZoneOffset offset2 = now.atZone(zoneId2).getOffset();
return offset1.compareTo(offset2);
}
}
enum OffsetBase {
GMT, UTC
}
}
结果如下:
(GMT+14:00) Pacific/Apia
(GMT+14:00) Pacific/Kiritimati
(GMT+14:00) Etc/GMT-14
这只是示例,因为列表很长
更新 基于请求者,因此要获取特定区域 ID 的 GMT。
public static List<String> getTimeZoneList(OffsetBase base, String wantedZoneId) {
LocalDateTime now = LocalDateTime.now();
return ZoneId.getAvailableZoneIds().stream()
.map(ZoneId::of)
.sorted(new ZoneComparator())
.filter(zoneId -> zoneId.getId().equals(wantedZoneId))
.map(id -> String.format(
"(%s%s) %s",
base, getOffset(now, id), id.getId()))
.collect(Collectors.toList());
}
这个功能是一样的,只是加上[过滤]功能
比方说,您的 ID 在 Set<String>
中,就像 ZoneId.getAvailableZoneIds()
.
您可以使用 ZoneId
来及时创建当前时刻并根据需要格式化其偏移量:
public static void main(String[] args) throws IOException {
// provide two formatters for the desired outputs GMT... and UTC...
DateTimeFormatter gmtFormatter = DateTimeFormatter.ofPattern("OOOO");
DateTimeFormatter utcFormatter = DateTimeFormatter.ofPattern("'UTC'xxx");
// stream all the IDs (sorted) and create a ZonedDateTime at each ZoneId
ZoneId.getAvailableZoneIds().stream().sorted().forEach(zoneId -> {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of(zoneId));
// then print the zone id and the other representations using the formatters
System.out.println(
String.format("%-32s %9s / %9s",
zoneId.toString(),
now.format(gmtFormatter),
now.format(utcFormatter)
));
});
}
第一个格式化程序只考虑 GMT+/-HH:mm 表示中的区域,第二个只考虑文字 UTC 加上偏移量为 +/-HH:mm.
(缩短!)输出是
Africa/Abidjan GMT / UTC+00:00
Africa/Accra GMT / UTC+00:00
Africa/Addis_Ababa GMT+03:00 / UTC+03:00
Africa/Algiers GMT+01:00 / UTC+01:00
Africa/Asmara GMT+03:00 / UTC+03:00
Africa/Asmera GMT+03:00 / UTC+03:00
Africa/Bamako GMT / UTC+00:00
...
US/Alaska GMT-09:00 / UTC-09:00
US/Aleutian GMT-10:00 / UTC-10:00
US/Arizona GMT-07:00 / UTC-07:00
US/Central GMT-06:00 / UTC-06:00
US/East-Indiana GMT-05:00 / UTC-05:00
US/Eastern GMT-05:00 / UTC-05:00
US/Hawaii GMT-10:00 / UTC-10:00
US/Indiana-Starke GMT-06:00 / UTC-06:00
US/Michigan GMT-05:00 / UTC-05:00
US/Mountain GMT-07:00 / UTC-07:00
US/Pacific GMT-08:00 / UTC-08:00
US/Samoa GMT-11:00 / UTC-11:00
UTC GMT / UTC+00:00
Universal GMT / UTC+00:00
W-SU GMT+03:00 / UTC+03:00
WET GMT / UTC+00:00
Zulu GMT / UTC+00:00
这是您的其他要求的想法,列出每个偏移量的城市:
public static void main(String[] args) throws IOException {
// provide two formatters for the desired outputs GMT... and UTC...
DateTimeFormatter gmtFormatter = DateTimeFormatter.ofPattern("OOOO");
DateTimeFormatter utcFormatter = DateTimeFormatter.ofPattern("'UTC'xxx");
// get a map of zones grouped by offset
Map<ZoneId, List<ZoneId>> zonesPerOffset =
ZoneId.getAvailableZoneIds().stream()
.map(ZoneId::of)
.collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(zoneId -> ZonedDateTime.now(zoneId).getOffset()));
// print them
zonesPerOffset.forEach((offset, zones) -> {
String o = ZonedDateTime.now(zones.get(0)).format(utcFormatter);
String zs = String.join(", ", zones.stream().map(zone -> {
String[] idParts = zone.getId().split("/");
return idParts[idParts.length - 1];
}).collect(Collectors.toList()));
String out = String.format("(%9s) %s", o, zs);
System.out.println(out);
});
}
输出(缩短):
(UTC+04:00) Yerevan, GMT-4, Dubai, Reunion, Mauritius, Saratov, Samara, Mahe, Baku, Muscat, Volgograd, Astrakhan, Tbilisi, Ulyanovsk
(UTC+00:00) London, GMT, GMT-0, Jersey, St_Helena, Guernsey, Isle_of_Man, GMT+0, Banjul, GMT, Freetown, GB-Eire, Bamako, GB, Conakry, Portugal, Universal, Sao_Tome, Nouakchott, Troll, UTC, Universal, Faeroe, Abidjan, Eire, Accra, Faroe, UCT, GMT0, Dublin, Zulu, Ouagadougou, Reykjavik, Madeira, Zulu, Iceland, Lisbon, Canary, Lome, Greenwich, Belfast, GMT0, Danmarkshavn, Dakar, Bissau, WET, Greenwich, Timbuktu, UCT, Monrovia, UTC
(UTC+08:00) Kuching, Chungking, GMT-8, Perth, Macao, Macau, Choibalsan, Shanghai, Ulan_Bator, Chongqing, Ulaanbaatar, Taipei, Manila, PRC, Ujung_Pandang, Harbin, Singapore, Brunei, West, Hong_Kong, Makassar, Hongkong, Kuala_Lumpur, Irkutsk, Singapore
(UTC+12:00) Kwajalein, Wallis, Funafuti, Nauru, Kwajalein, Wake, Norfolk, Tarawa, Kamchatka, GMT-12, Anadyr, Majuro
这样看起来不太好,但您可以根据需要应用过滤器。也许删除前导 UTC 等的元素,也许过滤掉特定的大陆,等等。
作为方法:
public static ZoneOffset getOffsetOf(ZoneId zoneId) {
return ZonedDateTime.now(zoneId).getOffset();
}
// this one may throw an Exception if you pass an invalid zoneId as String!
public static ZoneOffset getOffsetOf(String zoneId) {
return ZonedDateTime.now(ZoneId.of(zoneId)).getOffset();
}
public static List<ZoneId> getAllZoneIdsWith(ZoneOffset zoneOffset) {
return ZoneId.getAvailableZoneIds()
.stream()
.filter(zoneId -> ZonedDateTime.now(ZoneId.of(zoneId))
.getOffset().equals(zoneOffset))
.map(ZoneId::of)
.collect(Collectors.toList());
}
public static String getGmtFormat(ZoneId zoneId) {
return String.format("(%s) %s",
ZonedDateTime.now(zoneId)
.format(DateTimeFormatter.ofPattern("OOOO")),
zoneId.getId());
}
使用最后一种方法获取所有可用 ZoneId
s 的 GMT 格式:
List<String> gmtFormats = ZoneId.getAvailableZoneIds()
.stream()
.map(zone -> getGmtFormat(ZoneId.of(zone)))
.collect(Collectors.toList());