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?
Advertisement
Answer
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.
As methods:
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()); }
Use the last method in order to get the GMT formats of all available ZoneId
s:
List<String> gmtFormats = ZoneId.getAvailableZoneIds() .stream() .map(zone -> getGmtFormat(ZoneId.of(zone))) .collect(Collectors.toList());