Find standard time name for a region using Java

匆匆过客 提交于 2020-07-23 06:23:45

问题


Is there anyway to find the standard time that comes under time zone regions, for example

America/New_York and America/NewJersey -> EST

I am developing a REST service where the request will have region-based timezone(America/NewJersey) as a parameter and I need to find the standard time it comes under and pass it to legacy API, which only accepts 3 digit timezone(EST/MST/CST/AET).

I am using Java 8 and I checked Time API, but it doesn't have any such feature/functionality. As a workaround I can have a mapping in a file or DB, but just want to know if anybody else faced this and is there any clean solution to it.


回答1:


If I understand correctly, the main requirement is to have some specific three letter abbreviations that an API outside of your control requires. So for example:

  • EST for Eastern Standard Time (probably North American Eastern Standard Time?), not ET for Eastern Time.
  • On the other hand AET for Australian Eastern Time, not AEST for Australian Eastern Standard Time (and also not EST for Eastern Standard Time even though I have read that EST is used as abbreviation in Australia too).

It seems to me that there is no systematic correspondence between the time zone abbreviations that Java knows (from CLDR or what locale data provider you are using) and the abbreviations required by that API. As a further problem three letter time zone abbreviations are often ambiguous, so I suspect that there are many time zones that your legacy API is simply unable to recognize (or for which it requires some obscure homespun abbreviation that we have little chance of guessing).

Approaches are two:

  1. The safe but also circumstantial and laborious way is the one that Deadpool has long suggested in a comment: Build and keep a mapping of the abbreviations required.
  2. See how far you can get with the abbreviations that Java knows. Be prepared that you won’t be able to cover all cases and that you may make an incorrect guess occasionally.

I will leave option 1. to yourself with my recommendation.

In case you want to try your luck with option 2., my attempt follows.

private static final DateTimeFormatter ZONE_FORMATTER
        = DateTimeFormatter.ofPattern("zzz", Locale.ENGLISH);

private static String getThreeLetterAbbreviation(ZoneId zone) {
    // Try the display name first
    String displayName = zone.getDisplayName(TextStyle.SHORT_STANDALONE, Locale.ENGLISH);
    if (displayName.length() == 3) {
        return displayName;
    }
    
    // Try formatting a date in standard time; try southern hemisphere first
    ZonedDateTime timeInStandardTime = LocalDate.of(2021, Month.JULY, 1)
            .atStartOfDay(zone);
    if (zone.getRules().isDaylightSavings(timeInStandardTime.toInstant())) {
        // Then northern hemisphere
        timeInStandardTime = LocalDate.of(2021, Month.JANUARY, 1)
                .atStartOfDay(zone);
        if (zone.getRules().isDaylightSavings(timeInStandardTime.toInstant())) {
            throw new IllegalArgumentException("Unable to find a date in standard time");
        }
    }
    return timeInStandardTime.format(ZONE_FORMATTER);
}

This auxiliary method tries it out:

private static void printAbbreviation(String zid) {
    System.out.format("%19s -> %s%n", zid,
            getThreeLetterAbbreviation(ZoneId.of(zid)));
}

So using it we go:

    printAbbreviation("America/Los_Angeles");
    printAbbreviation("America/Denver");
    printAbbreviation("America/Chicago");
    printAbbreviation("America/New_York");
    printAbbreviation("Australia/Sydney");

Output:

America/Los_Angeles -> PST
     America/Denver -> MST
    America/Chicago -> CST
   America/New_York -> EST
   Australia/Sydney -> AET

I would not call it a clean solution. What I particularly fear about it is that the method will produce an incorrect result that your API interprets differently from the intended, and no one will notice that it in turn produces an incorrect result, or not until it’s too late. For example:

    printAbbreviation("Asia/Shanghai");
      Asia/Shanghai -> CST

Here CST is for China Standard Time, but my guess is that your API will understand it as North American Central Standard Time. We really should never rely on three letter time zone abbreviations. They are ambiguous, maybe more often than not. And as this question shows, they are not standardized.



来源:https://stackoverflow.com/questions/62839386/find-standard-time-name-for-a-region-using-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!