Java uses IANA time zone IDs in the form region/city. So if you can map your abbreviations to those, you can get through. For the sake of giving you working code, here’s an example but I guarantee that some of the IDs are not the ones you want. You will have to define your own mapping. Some of the long time zone names in your list do not refer to unique time zones, for example Gulf Standard Time and Central European Time. There are many time zones within those regions.
private static final Map<String, String> tzSubset = Map.ofEntries(
Map.entry("NZST", "Antarctica/McMurdo"),
Map.entry("AEST", "Australia/Sydney"),
Map.entry("JST", "Asia/Tokyo"),
Map.entry("HKT", "Asia/Hong_Kong"),
Map.entry("CST", "America/North_Dakota/New_Salem"), // not in China
Map.entry("SGT", "Asia/Singapore"),
Map.entry("IST", "Asia/Calcutta"),
Map.entry("GST", "Asia/Dubai"),
Map.entry("MSK", "Europe/Volgograd"),
Map.entry("SAST", "Africa/Mbabane"),
Map.entry("CET", "Africa/Ceuta"),
Map.entry("GMT", "Etc/GMT"),
Map.entry("BST", "Europe/Belfast"),
Map.entry("BRT", "America/Maceio"),
Map.entry("ET", "America/Indiana/Winamac")
);
private static final ZoneId targetTimeZone = ZoneId.of("America/Toronto");
With the mapping and the desired time zone in place, the conversion is simple enough:
LocalDateTime inputDateTime = LocalDateTime.of(2021, Month.JANUARY, 13, 23, 45);
String inputTimeZone = "BST";
ZoneId zone = ZoneId.of(inputTimeZone, tzSubset);
ZonedDateTime targetDateTime = inputDateTime.atZone(zone)
.withZoneSameInstant(targetTimeZone);
System.out.format("%s in %s equals %s%n", inputDateTime, zone, targetDateTime);
Output from this example snippet is:
2021-01-13T23:45 in Europe/London equals 2021-01-13T18:45-05:00[America/Toronto]
The conversion automatically accounts for summer time (DST) if either of the two time zones involved uses it.
Edit: It seems that you are assuming that the dates and times are current, not historical? You mentioned that America/Sao_Paulo dropped summer time in 2019 — so what if you have got a LocalDateTime
from 2019 or earlier? If you don’t plan to handle those correctly, you should definitely do a range check on your date time and refuse to convert it if falls outside your intended bounds. Use the isBefore
and/or the isAfter
method of LocalDateTime
.
Link: Oracle tutorial: Date Time explaining how to use java.time.