Показать все часовые пояса с GMT и UTC в Java

Показать все часовые пояса с GMT и UTC на Java

1. обзор

Всякий раз, когда мы имеем дело с временем и датами, нам нужна система отсчета. Стандарт для этого -UTC, но мы также видимGMT в некоторых приложениях.

Короче говоря, UTC - это стандарт, а GMT - часовой пояс.

Вот что Википедия говорит нам о том, что использовать:

В большинстве случаев UTC считается взаимозаменяемым со средним временем по Гринвичу (GMT), но научное сообщество более точно не определяет GMT.

Другими словами, как только мы составим список со смещениями часовых поясов в UTC, у нас будет он и для GMT.

Сначала мы рассмотрим способ достижения этого в Java 8, а затем увидим, как мы можем получить тот же результат в Java 7.

2. Получение списка зон

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

Для этого в классеZoneId есть удобный статический метод:

Set availableZoneIds = ZoneId.getAvailableZoneIds();

Затем мы можем использоватьSet для создания отсортированного списка часовых поясов с соответствующими смещениями:

public List getTimeZoneList(OffsetBase base) {

    LocalDateTime now = LocalDateTime.now();
    return ZoneId.getAvailableZoneIds().stream()
      .map(ZoneId::of)
      .sorted(new ZoneComparator())
      .map(id -> String.format(
        "(%s%s) %s",
        base, getOffset(now, id), id.getId()))
      .collect(Collectors.toList());
}

В приведенном выше методе используется параметрenum, который представляет смещение, которое мы хотим видеть:

public enum OffsetBase {
    GMT, UTC
}

Теперь давайте рассмотрим код более подробно.

После того, как мы получили все доступные идентификаторы зон, нам понадобится реальная временная привязка, представленнаяLocalDateTime.now().

После этого мы используем API JavaStream, чтобы перебирать каждую запись в нашем наборе идентификаторов часового поясаString и преобразовывать ее в список отформатированных часовых поясов с соответствующим смещением.

Для каждой из этих записей мы генерируем экземплярZoneId сmap(ZoneId::of).

3. Получение смещений

Нам также нужно найти фактические смещения UTC. Например, в случае Центральноевропейского времени смещение будет+01:00.с.

Чтобы получить смещение UTC для любой данной зоны, мы можем использовать методLocalDateTime’s getOffset().

Также обратите внимание, что Java представляет смещения+00:00 какZ.

Итак, чтобы иметь согласованный видString для часовых поясов с нулевым смещением, мы заменимZ на+00:00:

private String getOffset(LocalDateTime dateTime, ZoneId id) {
    return dateTime
      .atZone(id)
      .getOffset()
      .getId()
      .replace("Z", "+00:00");
}

4. Создание зонComparable

При желании мы также можем отсортировать часовые пояса по смещению.

Для этого воспользуемся классомZoneComparator:

private class ZoneComparator implements Comparator {

    @Override
    public int compare(ZoneId zoneId1, ZoneId zoneId2) {
        LocalDateTime now = LocalDateTime.now();
        ZoneOffset offset1 = now.atZone(zoneId1).getOffset();
        ZoneOffset offset2 = now.atZone(zoneId2).getOffset();

        return offset1.compareTo(offset2);
    }
}

5. Отображение часовых поясов

Все, что осталось сделать, это соединить вышеуказанные части вместе, вызвав методgetTimeZoneList() для каждого значенияOffsetBase enum и отобразив списки:

public class TimezoneDisplayApp {

    public static void main(String... args) {
        TimezoneDisplay display = new TimezoneDisplay();

        System.out.println("Time zones in UTC:");
        List utc = display.getTimeZoneList(
          TimezoneDisplay.OffsetBase.UTC);
        utc.forEach(System.out::println);

        System.out.println("Time zones in GMT:");
        List gmt = display.getTimeZoneList(
          TimezoneDisplay.OffsetBase.GMT);
        gmt.forEach(System.out::println);
    }
}

Когда мы запустим приведенный выше код, он напечатает часовые пояса для UTC и GMT.

Вот фрагмент того, как будет выглядеть результат:

Time zones in UTC:
(UTC+14:00) Pacific/Apia
(UTC+14:00) Pacific/Kiritimati
(UTC+14:00) Pacific/Tongatapu
(UTC+14:00) Etc/GMT-14

6. Java 7 и более ранние версии

Java 8 упрощает эту задачу за счет использования APIStream иDate and Time.

Однако, если у нас есть Java 7 и до проекта, мы все равно можем достичь того же результата, полагаясь на классjava.util.TimeZone с его методомgetAvailableIDs():

public List getTimeZoneList(OffsetBase base) {
    String[] availableZoneIds = TimeZone.getAvailableIDs();
    List result = new ArrayList<>(availableZoneIds.length);

    for (String zoneId : availableZoneIds) {
        TimeZone curTimeZone = TimeZone.getTimeZone(zoneId);
        String offset = calculateOffset(curTimeZone.getRawOffset());
        result.add(String.format("(%s%s) %s", base, offset, zoneId));
    }
    Collections.sort(result);
    return result;
}

Основным отличием кода Java 8 является расчет смещения.

rawOffset мы получаем изTimeZone()‘s getRawOffset() method expresses the time zone’s offset in milliseconds.

Следовательно, нам нужно преобразовать это в часы и минуты с помощью классаTimeUnit:

private String calculateOffset(int rawOffset) {
    if (rawOffset == 0) {
        return "+00:00";
    }
    long hours = TimeUnit.MILLISECONDS.toHours(rawOffset);
    long minutes = TimeUnit.MILLISECONDS.toMinutes(rawOffset);
    minutes = Math.abs(minutes - TimeUnit.HOURS.toMinutes(hours));

    return String.format("%+03d:%02d", hours, Math.abs(minutes));
}

7. Заключение

В этом кратком руководстве мы увидели, как составить список всех доступных часовых поясов с их смещениями по Гринвичу и Гринвичу.

И, как всегда, доступен полный исходный код примеровover on GitHub.