We keep time zones of the cities in our config table using ID of Time Zone values as Europe/London
, Asia/Tokyo
, etc. However, when selecting time zones from the list, user needs to see the GMT values for these time zones and we want to display Display Name of Time Zone Options as (UTC 00:00) Dublin, Edinburgh, Lisbon, London
rather than Europe/London
. As we know, the GMT values are not fixed and we should make some conversion in order to display the current time zone display value. So, how could I do this in Java?
CodePudding user response:
you can check this code below if return what you need:
public class Stackoverflow {
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
}
}
the result was as following :
(GMT 14:00) Pacific/Apia
(GMT 14:00) Pacific/Kiritimati
(GMT 14:00) Etc/GMT-14
this is just example as the list is very long
update based on requester, so to get GMT for specific zone id.
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());
}
this function is the same, just add [ filter ] function
CodePudding user response:
Let's say, you have the ids in a Set<String>
, just like ZoneId.getAvailableZoneIds()
.
You can use a ZoneId
in order to create the current moment in time and format its offset as desired:
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)
));
});
}
The first formatter only consider the zone in GMT /-HH:mm representation and the second one just the literals UTC plus the offset as /-HH:mm.
The (shortened!) output is
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
Here's an idea for your other requirement, listing cities for each offset:
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);
});
}
Output (shortened):
(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
Doesn't look that well this way, but you can apply filters as desired. Maybe remove elements with leading UTC and more, maybe filter out specific continents, whatever.