Java how to get list of timezone ids for a given temporary abbreviation

Can you find a list of time zone IDs for this reduced zone? For example, for the abbreviation IST

, the time zone identifier Asia/Jerusalem

, Asia/Kolkata

and Europe/Dublin

.

+2


source to share


3 answers


Interest Ask. Since acronyms are not standardized, there can be no authoritative answer or a bulletproof way to get such an answer. From head to head, I thought of two approaches:

  • Get them from your JVM.
  • Find them online.

Getting zones from your JVM:

    String givenAbbr = "IST";
    LocalDateTime summerSouthernHemisphere = LocalDate.of(2018, Month.JANUARY, 31).atStartOfDay();
    LocalDateTime summerNorthernHemisphere = LocalDate.of(2018, Month.JULY, 31).atStartOfDay();
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("z");
    Set<ZoneId> zones = new HashSet<>();
    for (String id : ZoneId.getAvailableZoneIds()) {
        ZoneId zone = ZoneId.of(id);
        String abbr = summerSouthernHemisphere.atZone(zone).format(dtf);
        if (abbr.equals(givenAbbr)) {
            zones.add(zone);
        }
        abbr = summerNorthernHemisphere.atZone(zone).format(dtf);
        if (abbr.equals(givenAbbr)) {
            zones.add(zone);
        }
    }
    System.out.println(zones);

      

Prints:

[Asia/Calcutta, Eire, Europe/Dublin, Asia/Jerusalem, Asia/Tel_Aviv, Israel, Asia/Kolkata, Asia/Colombo]

      

Some of them are just names for the same time zone. For example, Eire has the same rules as Europe / Dublin. Therefore, if desired, additional filtration could be performed. You can use oneZoneId.getRules().equals(anotherZoneId.getRules())

to determine if two objects ZoneId

have the same zone rules.



For the abbreviation CST, the list is even longer and has more synonyms:

[PRC, America/Matamoros, Asia/Taipei, America/Regina, America/El_Salvador,
        America/North_Dakota/New_Salem, Asia/Harbin, America/Costa_Rica,
        America/North_Dakota/Center, America/Guatemala, America/Winnipeg,
        Asia/Chongqing, America/Rankin_Inlet, America/Indiana/Knox,
        America/Belize, SystemV/CST6CDT, Mexico/General,
        America/North_Dakota/Beulah, CST6CDT, America/Swift_Current,
        America/Knox_IN, Asia/Chungking, Asia/Macao, Asia/Shanghai,
        America/Indiana/Tell_City, America/Menominee, America/Bahia_Banderas,
        America/Managua, Canada/East-Saskatchewan, Asia/Macau, America/Havana,
        America/Resolute, US/Central, US/Indiana-Starke, Cuba, America/Monterrey,
        America/Chicago, America/Merida, America/Mexico_City, Canada/Central,
        America/Tegucigalpa, America/Rainy_River, Canada/Saskatchewan, SystemV/CST6]

      

One limitation of my approach is that some time zones are known with more than one name and therefore more than three or four letter abbreviations. My code above only catches one of them.

Another limitation is that choosing two dates like me will never give you all the possibilities in the past and future, and may even miss something where I just didn't hit the right date. I tried to pick one day when winter is in the northern hemisphere and summer is in the south, and the other way around. This will cover most cases to date, but you never know if there is a time zone or three where the transition does not follow in the summer and winter as we know it. If you want to improve your lighting, there are some great suggestions in Hugos's answer .

Get them from the internet

Another answer is, of course, the fact that your search is undeniable: such lists are published on the Internet. For example Wikipedia List of Time Zone Abbreviations and Time Zone Abbreviations - Worldwide List at timeanddate.com . As expected, both lists mentioned disagree. For example, the latter knows two interpretations of the ADT, the former only one. The last list gives many abbreviations for synonyms and thus illustrates my point above that each zone can have more than one abbreviation.

+3


source


@Ole VV's answer already gives a lot of details, like the fact that three letter acronyms (like IST

or PST

) are ambiguous and not standard and you should prefer the long IANA time zone names (always in a format Continent/City

like Asia/Kolkata

or Europe/Berlin

).

But this answer has one tricky detail: it accepts January and July 2018 as the base dates for winter and summer (so the acronym can be checked against standard and summer periods). But this did not guarantee that for all cases it would take both winter and summer time, because the time zone rules can change - just because a time zone today has a DST does not mean it will be forever (the reverse is also true) ...

So, instead of picking a date / time and hoping that all timezones have a DST change in between, the best approach is to get all changes from the object ZoneRules

- it contains all transitions from strong> dates (the moment the offset changes for that timezone is from -for the beginning / end of DST or because some governments have decided that their country will now be in a different time zone).

It also covers the case where the timezone used an abbreviation in the past, but then changed to a different one as I check the history of changes in the timezone.

The code is very similar. The only difference is that instead of using a fixed date (Jan / Jul 2018) I loop through all zone transitions (and if there are no transitions in the time zone, which means it never had DST or any other changes) I getting the current date). I also created Set

from String

(as you only want names, but you can also store objects ZoneId

):

String ist = "IST";
Set<String> zones = new HashSet<>();
// formatter to get the abbreviation
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("z");
for (String id : ZoneId.getAvailableZoneIds()) {
    ZoneId zone = ZoneId.of(id);
    ZoneRules rules = zone.getRules();
    List<ZoneOffsetTransition> transitions = rules.getTransitions();
    if (transitions.isEmpty()) {
        // no transitions found, just pick any date
        String abbrev = fmt.format(ZonedDateTime.now(zone));
        if (ist.equals(abbrev)) {
            zones.add(id);
        }
    } else {
        for (ZoneOffsetTransition transition : transitions) {
            // get the instant that the transition occurred and convert to this zone
            String abbrev = fmt.format(transition.getInstant().atZone(zone));
            if (ist.equals(abbrev)) {
                zones.add(id);
            }
        }
    }
}

System.out.println(zones);

      

The output in this case will be the same:

[Asia / Calcutta, Air, Europe / Dublin, Asia / Jerusalem, Asia / Tel Aviv, Israel, Asia / Kolkata, Asia / Colombo]

While this code looks more redundant (since it goes through all the dates the DST changes occurred), it is more guaranteed to get all cases. If you are looking for a timezone that had daylight saving time in the past, but it will not be in 2018 (or any other arbitrary date you get), using that arbitrary date will not work. Only by checking all transitions can you be sure that all cases have been covered.

One example: if instead of IST

, I want to check the abbreviation AEDT

(Australian Eastern Daylight Time).

Using @Ole VV code, I get:



[Australia / Sydney, Australia / Melbourne, Australia / Hobart, Australia / Victoria, Australia / ACT, Australia / Canberra, Australia / NSW, Australia / Tasmania, Australia / Currie]

Using my code, I get:

Australia, Australia / Australia, Australia / Australia, Australia / Australia, Australia / Australia, Australia / Australia, Australia / Australia, Australia / Australia, Australia / Australia, Australia / Australia, Australia / Lindeman]

Pay attention to the differences. One example is Australia/Brisbane

one that had DST until the 90s , but now it doesn't (so it won't be in 2018 either ). So, if you try to get AEDT (Daylight Saving Time) in 2018, that time zone will not be selected by @Ole VV code because it will not have DST in 2018.

But I check all the changes he had during history, no matter when it happened. This will ensure that I cover all cases.

PS: if you want to get abbreviations that were valid on a specific date, you can use @Ole VV code (just change the dates accordingly).


Another way (not easier) is to download the IANA timezone database file and follow this tutorial to understand how to read the files (not trivial, IMO). Take, for example, a record in Dublin:

# Zone  NAME        GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Europe/Dublin   -0:25:00 -  LMT 1880 Aug  2
            -0:25:21 -  DMT 1916 May 21  2:00 # Dublin MT
            -0:25:21 1:00   IST 1916 Oct  1  2:00s
             0:00   GB-Eire %s  1921 Dec  6 # independence
             0:00   GB-Eire GMT/IST 1940 Feb 25  2:00
             0:00   1:00    IST 1946 Oct  6  2:00
... etc

      

You can see what is IST

used for Europe/Dublin

. Well, this is not the easiest way, but every time IANA updates its database it takes a while for the JDK to change (although you can only update the timezone data if you like).

So, if you want the most up-to-date information, you can check the IANA website regularly for updates.

+1


source


Refer to Java 8 docs for ZoneDateTime api in oracle docs.

Link an example maven project on github implementing this method.

Implementation wise you can use below code,

ZoneId losAngeles = ZoneId.of("America/Los_Angeles");
ZoneId berlin = ZoneId.of("Europe/Berlin");

// 2014-02-20 12:00
LocalDateTime dateTime = LocalDateTime.of(2014, 02, 20, 12, 0);

// 2014-02-20 12:00, Europe/Berlin (+01:00)
ZonedDateTime berlinDateTime = ZonedDateTime.of(dateTime, berlin);

// 2014-02-20 03:00, America/Los_Angeles (-08:00)
ZonedDateTime losAngelesDateTime = berlinDateTime.withZoneSameInstant(losAngeles);

int offsetInSeconds = losAngelesDateTime.getOffset().getTotalSeconds(); // -28800

// a collection of all available zones
Set<String> allZoneIds = ZoneId.getAvailableZoneIds();

      

-1


source







All Articles