Найдите стандартное название времени для региона, используя Java - PullRequest
0 голосов
/ 10 июля 2020

Есть ли способ найти стандартное время, которое соответствует регионам часовых поясов, например

America/New_York and America/NewJersey -> EST

Я разрабатываю службу REST, в которой запрос будет иметь часовой пояс на основе региона (Америка / Нью-Джерси) как параметр, и мне нужно найти стандартное время, в которое он входит, и передать его в устаревший API, который принимает только 3 di git часовой пояс (EST / MST / CST / AET).

Я использую Java 8, и я проверил Time API, но у него нет такой функции / функциональности. В качестве обходного пути у меня может быть отображение в файле или БД, но я просто хочу знать, сталкивался ли кто-нибудь еще с этим и есть ли какое-нибудь чистое решение для этого.

1 Ответ

2 голосов
/ 11 июля 2020

Если я правильно понимаю, основным требованием является наличие некоторых специфических c трехбуквенных сокращений, которые требуются API вне вашего контроля. Так, например:

  • EST для восточного стандартного времени (вероятно, североамериканское восточное стандартное время?), А не ET для восточного времени.
  • С другой стороны, AET для восточного времени Австралии, не AEST для восточного стандартного времени Австралии (а также не EST для восточного стандартного времени, хотя я читал, что EST также используется как сокращение в Австралии).

Мне кажется, c соответствие между сокращениями часовых поясов, которые известны Java (из CLDR или от поставщика данных локали, который вы используете), и сокращений, требуемых этим API. В качестве дополнительной проблемы трехбуквенные сокращения часовых поясов часто неоднозначны, поэтому я подозреваю, что существует много часовых поясов, которые ваш устаревший API просто не может распознать (или для которых требуется какая-то неясная аббревиатура домотканой, которую у нас мало шансов угадать).

Есть два подхода:

  1. Безопасный, но также обстоятельный и трудоемкий способ - это тот, который Дэдпул давно предлагал в своем комментарии: Создайте и сохраните карту необходимых сокращений.
  2. Посмотрите, как далеко вы можете зайти с сокращениями, которые знает Java. Будьте готовы к тому, что вы не сможете охватить все случаи и что иногда вы можете сделать неверное предположение.

Я оставлю вариант 1. с моей рекомендацией.

Если вы хотите испытать удачу с вариантом 2, моя попытка следует.

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);
}

Этот вспомогательный метод пробует его:

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

Итак, используя его, мы go:

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

Вывод:

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

Я бы не назвал это чистым решением. Я особенно опасаюсь того, что метод выдаст неправильный результат, который ваш API интерпретирует иначе, чем предполагалось, и никто не заметит, что он, в свою очередь, дает неправильный результат, или только когда станет слишком поздно. Например:

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

Здесь CST для китайского стандартного времени, но я предполагаю, что ваш API будет понимать его как североамериканское центральное стандартное время. Нам действительно не следует никогда полагаться на трехбуквенные сокращения часовых поясов. Они неоднозначны, может быть, чаще всего. И, как показывает этот вопрос, они не стандартизированы.

...