Выдача часового пояса в Java - PullRequest
0 голосов
/ 15 февраля 2020

Я использую этот простой код для получения идентификаторов часовых поясов текущего часового пояса, установленного в системе.

public class Main {

    public static void main(String[] args)
    {   TimeZone timezone = TimeZone.getDefault();
        System.out.println(timezone.getID());
    }
}

Я использую tzutil /g для определения часового пояса и tzutil /s, чтобы установить часовой пояс. Я наблюдал, когда часовой пояс установлен на Восточное стандартное время , приведенный выше код возвращает идентификатор как America/New_York, но когда он установлен на Восточное стандартное время_dstoff , тогда я получаю идентификатор как GMT-05:00 что нежелательно. Я хочу вывод в виде континент / город .

Как бы это получить?

Ответы [ 2 ]

1 голос
/ 15 февраля 2020

Чтобы найти часовые пояса, которые есть и были всегда GMT-05:00, он же Eastern Standard Time_dstoff, проверьте все ZoneId правила, чтобы найти один с:

  • Смещение -5 часов

  • Нет переходов (прошлые изменения часового пояса)

  • Нет правил перехода (текущий и будущий изменения часового пояса)

for (String id : ZoneId.getAvailableZoneIds()) {
    ZoneRules rules = ZoneId.of(id).getRules();
    if (rules.getTransitions().isEmpty() && rules.getTransitionRules().isEmpty()
                && rules.getOffset(Instant.now()).getTotalSeconds() == 5 * -3600) {
        System.out.println(id);
    }
}

Выход (OpenJDK 13.0.2 на Windows)

Etc/GMT+5
SystemV/EST5

Так что если вам нужно изменить часовой пояс с GMT-05:00 на зону с /, используйте один из этих двух. Etc/GMT+5 кажется уместным.

Если вы хотите автоматизировать это, поэтому он пытается это исправить, если часовой пояс по умолчанию не содержит /, тогда что-то вроде этого может работать:

if (! ZoneId.systemDefault().getId().contains("/")) {
    int offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).getTotalSeconds();
    String candidate = null;
    for (String id : ZoneId.getAvailableZoneIds()) {
        ZoneRules rules = ZoneId.of(id).getRules();
        if (rules.getTransitions().isEmpty() && rules.getTransitionRules().isEmpty()
                       && rules.getOffset(Instant.now()).getTotalSeconds() == offset) {
            if (id.startsWith("Etc/GMT")) {
                candidate = id;
                break;
            }
            if (candidate == null)
                candidate = id;
        }
    }
    if (candidate != null)
        TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of(candidate)));
}
1 голос
/ 15 февраля 2020

Мой первый ответ: вам не нужно беспокоиться о настройке часового пояса по умолчанию в вашей JVM. Ваш Java код не должен полагаться на него в любом случае. Установку по умолчанию можно изменить в любой момент из другой части вашей программы или из другой программы, работающей в той же JVM, как и fr agile. Вместо этого укажите явный часовой пояс в ваших чувствительных к часовому поясу операциях.

Если вы все еще хотите полагаться на значение по умолчанию, вот хак, чтобы установить его на некоторый континент / город часовой пояс, если это произойдет быть GMT-05:00, что вы считаете нежелательным.

    ZoneId defaultZoneId = ZoneId.systemDefault();
    ZoneId desiredTimeZone = null;
    if (defaultZoneId.equals(ZoneId.of("GMT-05:00"))) {
        // Pick a date in summer
        LocalDate dateInSummer = Year.now().atMonthDay(MonthDay.of(Month.JULY, 7));
        DateTimeFormatter zoneFormatter = DateTimeFormatter.ofPattern("zzzz", Locale.ENGLISH);
        for (String zid : ZoneId.getAvailableZoneIds()) {
            ZoneId zone = ZoneId.of(zid);
            String timeZoneName = dateInSummer.atStartOfDay(zone).format(zoneFormatter);
            if (zid.startsWith("America/") && timeZoneName.equals("Eastern Standard Time")) {
                desiredTimeZone = zone;
                break;
            }
        }
    }

    System.out.println("Time zone: " + desiredTimeZone);

На моем JDK 11 я получил:

Часовой пояс: Америка / Панама

Чтобы установить его как значение по умолчанию, мы, к сожалению, должны go через плохо спроектированный и в противном случае давно устаревший класс TimeZone:

    TimeZone.setDefault(TimeZone.getTimeZone(desiredTimeZone));

Есть еще одна причина, чтобы предостеречь от использования Америки / Панамы или некоторых других идентификатор часового пояса вместо GMT-05: 00: хотя в Панаме с некоторого времени 1908 года смещение -05: 00 от GMT / UT C используется не всегда, поэтому для исторических дат c вы получите неправильное время его использования.

Согласно timeanddate.com, места, которые используют восточное стандартное время в течение всего года (без летнего времени / летнего времени):

  • Нунавут - только остров Саутгемптон ( Корал Харбор) (Канада) (Америка / Кор часовой пояс al_Harbour)
  • Кинтана-Роо (Мексика) (часовой пояс Америки / Канкуна)
  • Каймановы острова (Америка / Кайман)
  • Ямайка (Америка / Ямайка)
  • Панама (Америка / Панама)

Мой Java дополнительно перечисляет Америку / Атикокан (также в Канаде).

В списке нет места в Соединенных Штатах. Состояния. Я считаю, что ни один из вышеперечисленных не всегда использовал смещение -05:00. То есть каждый из них имел разное смещение в определенный момент истории, и Java будет использовать это разное смещение для исторических дат c.

Так какой часовой пояс использовать?

Редактировать: Андреас в комментарии указал, что ни у Etc / GMT + 5, ни у SystemV / EST5 нет проблемы, о которой я упоминал, относительно применения смещений к историческим датам c, которые, вероятно, являются неожиданными. Так что вы можете рассмотреть один из них. Плюсы каждого, как я их вижу:

                                    America/Xxx Etc/GMT+5 SystemV/EST5 GMT-05:00
Official IANA time zone?                Yes        Yes
With slash?                             Yes        Yes        Yes
Continent/city?                         Yes
Good for historical dates?                         Yes        Yes         Yes
Prints as EST/Eastern Standard Time?    Yes                   Yes

(Ваша отправная точка, GMT-05: 00, включена только для сравнения. И какие из них действительно хороши для исторических дат c конечно, зависит от того, что вам нужно для них.)

Ссылки

...