Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does java.time.ZoneId not implement the Comparable interface?

Tags:

java

Just out of curiosity, why shouldn't I be able to compare time zones?

One timezone could be -2:00 related to UTC while another one would be +2:00 for example. Why not consider those as -2:00 < +2:00 and so on?

like image 222
user15013406 Avatar asked Sep 07 '21 17:09

user15013406


People also ask

What is ZoneId in Java?

A ZoneId is used to identify the rules used to convert between an Instant and a LocalDateTime . There are two distinct types of ID: Fixed offsets - a fully resolved offset from UTC/Greenwich, that uses the same offset for all local date-times.

Is ZonedDateTime a UTC?

A ZonedDateTime represents a date-time with a time offset and/or a time zone in the ISO-8601 calendar system. On its own, ZonedDateTime only supports specifying time offsets such as UTC or UTC+02:00 , plus the SYSTEM time zone ID.

Is ZonedDateTime immutable?

ZonedDateTime is an immutable representation of a date-time with a time-zone. This class stores all date and time fields, to a precision of nanoseconds, and a time-zone, with a zone offset used to handle ambiguous local date-times. For example, the value "2nd October 2007 at 13:45.30.

What is ZoneOffset UTC?

ZoneOffset extends ZoneId and defines the fixed offset of the current time-zone with GMT/UTC, such as +02:00. This means that this number represents fixed hours and minutes, representing the difference between the time in current time-zone and GMT/UTC: LocalDateTime now = LocalDateTime.

What is the use of zoneid in Java?

Java ZoneId class specifies a time zone identifier and provides a rule for converting between an Instant and a LocalDateTime. It inherits Object class and implements the Serializable interface. Let's see the declaration of java.time.ZoneId class. It is used to get the textual representation of the zone, such as 'India Time' or '+05:30'.

What is the use of Comparable interface in Java?

The Comparable interface is used to compare an object of the same class with an instance of that class, it provides ordering of data for objects of the user-defined class. The class has to implement the java.lang.Comparable interface to compare its instance, it provides the compareTo method that takes a parameter of the object of that class.

How to update timezone data without changing the Java version?

But this information can be updated without changing the Java version (using the Timezone Updater Tool ). If the timezone data is updated (but Java version stays the same) and a new zone ID is created, there would be no equivalent Enum for it, leaving the API "incomplete".

What is the use of short time-zone IDs in Java?

A zone map overrides to enable the short time-zone names to be used. The use of short zone IDs has been deprecated in java.util.TimeZone. This map allows the IDs to still be used via the of (String, Map) factory method.


Video Answer


2 Answers

Since ZoneId encode Time Zones and it change the offset respect UTC, there is not an order.

That's why ZoneOffset implements Comparable<ZoneOffset> since it is a fixed offset.

(Additional note)

For example:

Canada/Newfoundland -02:30/-03:30 ~ America/Belem -03:00/-03:00

where sometimes the order of Newfoundland ~ Belem is -02:30 > -03:00 but sometimes is -03:30 < -03:00.

A simple way to list all (from now up to four years) zone id pairs where the offset order change from A < B to B < A could be:

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class ZoneIdOrderChanges {

    public static void main(String... args) {

        // all zones
        List<ZoneId> zonesId = ZoneId.getAvailableZoneIds().stream().map(ZoneId::of).collect(toList());

        // all combinations two by two without repetition
        final List<Tuple<ZoneId, ZoneId>> pairs = IntStream.range(1, zonesId.size()).boxed().flatMap(a ->
                IntStream.range(a + 1, zonesId.size()).mapToObj(b ->
                        new Tuple<>(zonesId.get(a), zonesId.get(b)))).collect(toList());

        // from now up to 4 years after now
        OffsetDateTime t0 = OffsetDateTime.now();
        OffsetDateTime t = OffsetDateTime.now();
        OffsetDateTime sentry = t.plus(4, ChronoUnit.YEARS);

        BiFunction<OffsetDateTime, Integer, Integer> compareZones = (d, i) ->
                Integer.compare(ZonedDateTime.ofInstant(d.toInstant(), pairs.get(i).a).getOffset()
                        .compareTo(ZonedDateTime.ofInstant(d.toInstant(), pairs.get(i).b).getOffset()), 0);

        Function<OffsetDateTime, int[]> forder = z -> IntStream
                .range(0, pairs.size())
                .map(i -> compareZones.apply(z, i))
                .toArray();

        int[] order = forder.apply(t);

        Set<String> examples = new HashSet<>();

        while (t.compareTo(sentry) <= 0) {
            int[] o = forder.apply(t);
            if (Arrays.compare(order, o) != 0) {
                for (int i = 0; i < o.length; i++)
                    // only interested in not equals cases
                    if (order[i] != o[i] && order[i] != 0 && o[i] != 0) {
                        final OffsetDateTime tt = t;
                        String example = Stream.of(pairs.get(i).a, pairs.get(i).b)
                                .map(z -> String.format("%s %s/%s",
                                        z.getId(),
                                        ZonedDateTime.ofInstant(t0.toInstant(), z).getOffset(),
                                        ZonedDateTime.ofInstant(tt.toInstant(), z).getOffset()))
                                .collect(joining(" ~ "));
                        if (!examples.contains(example)) {
                            examples.add(example);
                            System.out.println(example);
                        }
                    }
            }
            t = t.plus(1, ChronoUnit.DAYS);
        }

    }

    @Getter
    @Setter
    @AllArgsConstructor
    static class Tuple<A, B> {
        private A a;
        private B b;
    }

}

with output (for that time interval and current rules)

Asia/Yerevan +04:00/+04:00 ~ Iran +04:30/+03:30
Asia/Yerevan +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Etc/GMT-4 +04:00/+04:00 ~ Iran +04:30/+03:30
Etc/GMT-4 +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Asia/Dubai +04:00/+04:00 ~ Iran +04:30/+03:30
Asia/Dubai +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Indian/Reunion +04:00/+04:00 ~ Iran +04:30/+03:30
Indian/Reunion +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Indian/Mauritius +04:00/+04:00 ~ Iran +04:30/+03:30
Indian/Mauritius +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Europe/Saratov +04:00/+04:00 ~ Iran +04:30/+03:30
Europe/Saratov +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Europe/Samara +04:00/+04:00 ~ Iran +04:30/+03:30
Europe/Samara +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Indian/Mahe +04:00/+04:00 ~ Iran +04:30/+03:30
Indian/Mahe +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Asia/Baku +04:00/+04:00 ~ Iran +04:30/+03:30
Asia/Baku +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Asia/Muscat +04:00/+04:00 ~ Iran +04:30/+03:30
Asia/Muscat +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Europe/Volgograd +04:00/+04:00 ~ Iran +04:30/+03:30
Europe/Volgograd +04:00/+04:00 ~ Asia/Tehran +04:30/+03:30
Iran +04:30/+03:30 ~ Europe/Astrakhan +04:00/+04:00
Iran +04:30/+03:30 ~ Asia/Tbilisi +04:00/+04:00
Iran +04:30/+03:30 ~ Europe/Ulyanovsk +04:00/+04:00
Asia/Tehran +04:30/+03:30 ~ Europe/Astrakhan +04:00/+04:00
Asia/Tehran +04:30/+03:30 ~ Asia/Tbilisi +04:00/+04:00
Asia/Tehran +04:30/+03:30 ~ Europe/Ulyanovsk +04:00/+04:00
Pacific/Fakaofo +13:00/+13:00 ~ NZ-CHAT +12:45/+13:45
Pacific/Fakaofo +13:00/+13:00 ~ Pacific/Chatham +12:45/+13:45
NZ-CHAT +12:45/+13:45 ~ Pacific/Enderbury +13:00/+13:00
NZ-CHAT +12:45/+13:45 ~ Pacific/Tongatapu +13:00/+13:00
NZ-CHAT +12:45/+13:45 ~ Etc/GMT-13 +13:00/+13:00
Pacific/Chatham +12:45/+13:45 ~ Pacific/Enderbury +13:00/+13:00
Pacific/Chatham +12:45/+13:45 ~ Pacific/Tongatapu +13:00/+13:00
Pacific/Chatham +12:45/+13:45 ~ Etc/GMT-13 +13:00/+13:00
Pacific/Yap +10:00/+10:00 ~ Australia/Yancowinna +09:30/+10:30
Pacific/Yap +10:00/+10:00 ~ Australia/Adelaide +09:30/+10:30
Pacific/Yap +10:00/+10:00 ~ Australia/Broken_Hill +09:30/+10:30
Pacific/Yap +10:00/+10:00 ~ Australia/South +09:30/+10:30
Pacific/Port_Moresby +10:00/+10:00 ~ Australia/Yancowinna +09:30/+10:30
Pacific/Port_Moresby +10:00/+10:00 ~ Australia/Adelaide +09:30/+10:30
Pacific/Port_Moresby +10:00/+10:00 ~ Australia/Broken_Hill +09:30/+10:30
Pacific/Port_Moresby +10:00/+10:00 ~ Australia/South +09:30/+10:30
Australia/Yancowinna +09:30/+10:30 ~ Pacific/Chuuk +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Australia/Queensland +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Pacific/Guam +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Pacific/Truk +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Asia/Vladivostok +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Pacific/Saipan +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Antarctica/DumontDUrville +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Australia/Brisbane +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Etc/GMT-10 +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Asia/Ust-Nera +10:00/+10:00
Australia/Yancowinna +09:30/+10:30 ~ Australia/Lindeman +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Pacific/Chuuk +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Australia/Queensland +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Pacific/Guam +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Pacific/Truk +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Asia/Vladivostok +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Pacific/Saipan +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Antarctica/DumontDUrville +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Australia/Brisbane +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Etc/GMT-10 +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Asia/Ust-Nera +10:00/+10:00
Australia/Adelaide +09:30/+10:30 ~ Australia/Lindeman +10:00/+10:00
Pacific/Chuuk +10:00/+10:00 ~ Australia/Broken_Hill +09:30/+10:30
Pacific/Chuuk +10:00/+10:00 ~ Australia/South +09:30/+10:30
Australia/Queensland +10:00/+10:00 ~ Australia/Broken_Hill +09:30/+10:30
Australia/Queensland +10:00/+10:00 ~ Australia/South +09:30/+10:30
Australia/Broken_Hill +09:30/+10:30 ~ Pacific/Guam +10:00/+10:00
Australia/Broken_Hill +09:30/+10:30 ~ Pacific/Truk +10:00/+10:00
Australia/Broken_Hill +09:30/+10:30 ~ Asia/Vladivostok +10:00/+10:00
Australia/Broken_Hill +09:30/+10:30 ~ Pacific/Saipan +10:00/+10:00
Australia/Broken_Hill +09:30/+10:30 ~ Antarctica/DumontDUrville +10:00/+10:00
Australia/Broken_Hill +09:30/+10:30 ~ Australia/Brisbane +10:00/+10:00
Australia/Broken_Hill +09:30/+10:30 ~ Etc/GMT-10 +10:00/+10:00
Australia/Broken_Hill +09:30/+10:30 ~ Asia/Ust-Nera +10:00/+10:00
Australia/Broken_Hill +09:30/+10:30 ~ Australia/Lindeman +10:00/+10:00
Pacific/Guam +10:00/+10:00 ~ Australia/South +09:30/+10:30
Pacific/Truk +10:00/+10:00 ~ Australia/South +09:30/+10:30
Asia/Vladivostok +10:00/+10:00 ~ Australia/South +09:30/+10:30
Pacific/Saipan +10:00/+10:00 ~ Australia/South +09:30/+10:30
Antarctica/DumontDUrville +10:00/+10:00 ~ Australia/South +09:30/+10:30
Australia/South +09:30/+10:30 ~ Australia/Brisbane +10:00/+10:00
Australia/South +09:30/+10:30 ~ Etc/GMT-10 +10:00/+10:00
Australia/South +09:30/+10:30 ~ Asia/Ust-Nera +10:00/+10:00
Australia/South +09:30/+10:30 ~ Australia/Lindeman +10:00/+10:00
Etc/GMT-1 +01:00/+01:00 ~ Antarctica/Troll +02:00/Z
Africa/Tunis +01:00/+01:00 ~ Antarctica/Troll +02:00/Z
Africa/Malabo +01:00/+01:00 ~ Antarctica/Troll +02:00/Z
America/Godthab -02:00/-03:00 ~ America/St_Johns -02:30/-02:30
America/Godthab -02:00/-03:00 ~ Canada/Newfoundland -02:30/-02:30
Africa/Lagos +01:00/+01:00 ~ Antarctica/Troll +02:00/Z
Africa/Algiers +01:00/+01:00 ~ Antarctica/Troll +02:00/Z
Africa/Ndjamena +01:00/+01:00 ~ Antarctica/Troll +02:00/Z
Antarctica/Troll +02:00/Z ~ Africa/Libreville +01:00/+01:00
Antarctica/Troll +02:00/Z ~ Africa/El_Aaiun +01:00/+01:00
Antarctica/Troll +02:00/Z ~ Africa/Douala +01:00/+01:00
Antarctica/Troll +02:00/Z ~ Africa/Brazzaville +01:00/+01:00
Antarctica/Troll +02:00/Z ~ Africa/Porto-Novo +01:00/+01:00
Antarctica/Troll +02:00/Z ~ Africa/Casablanca +01:00/+01:00
Antarctica/Troll +02:00/Z ~ Africa/Luanda +01:00/+01:00
Antarctica/Troll +02:00/Z ~ Africa/Kinshasa +01:00/+01:00
Antarctica/Troll +02:00/Z ~ Africa/Bangui +01:00/+01:00
Antarctica/Troll +02:00/Z ~ Africa/Niamey +01:00/+01:00
America/Asuncion -04:00/-03:00 ~ SystemV/AST4ADT -03:00/-04:00
Chile/Continental -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
Chile/Continental -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Argentina/Catamarca -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
America/Argentina/Catamarca -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
Canada/Atlantic -03:00/-04:00 ~ America/Asuncion -04:00/-03:00
America/Argentina/Cordoba -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
America/Argentina/Cordoba -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Araguaina -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
America/Araguaina -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Argentina/Salta -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
America/Argentina/Salta -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
Etc/GMT+3 -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
Etc/GMT+3 -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Montevideo -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
America/Montevideo -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
Brazil/East -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
Brazil/East -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Argentina/Mendoza -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
America/Argentina/Mendoza -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Argentina/Rio_Gallegos -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
America/Argentina/Rio_Gallegos -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Catamarca -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
America/Catamarca -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Cordoba -03:00/-03:00 ~ America/St_Johns -02:30/-03:30
America/Cordoba -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/St_Johns -02:30/-03:30 ~ America/Sao_Paulo -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Argentina/Jujuy -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Cayenne -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Recife -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Buenos_Aires -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Paramaribo -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Mendoza -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Santarem -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Asuncion -04:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Maceio -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ Atlantic/Stanley -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ Antarctica/Rothera -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Argentina/San_Luis -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Santiago -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Argentina/Ushuaia -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ Antarctica/Palmer -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Punta_Arenas -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Fortaleza -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Argentina/La_Rioja -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Belem -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Jujuy -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Bahia -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Argentina/San_Juan -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Argentina/ComodRivadavia -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Argentina/Tucuman -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Rosario -03:00/-03:00
America/St_Johns -02:30/-03:30 ~ America/Argentina/Buenos_Aires -03:00/-03:00
America/Sao_Paulo -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Argentina/Jujuy -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Cayenne -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Recife -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Buenos_Aires -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Paramaribo -03:00/-03:00 ~ Canada/Newfoundland -02:30/-03:30
America/Moncton -03:00/-04:00 ~ America/Asuncion -04:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Mendoza -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Santarem -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Asuncion -04:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Maceio -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ Atlantic/Stanley -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ Antarctica/Rothera -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Argentina/San_Luis -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Santiago -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Argentina/Ushuaia -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ Antarctica/Palmer -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Punta_Arenas -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Fortaleza -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Argentina/La_Rioja -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Belem -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Jujuy -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Bahia -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Argentina/San_Juan -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Argentina/ComodRivadavia -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Argentina/Tucuman -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Rosario -03:00/-03:00
Canada/Newfoundland -02:30/-03:30 ~ America/Argentina/Buenos_Aires -03:00/-03:00
America/Asuncion -04:00/-03:00 ~ Atlantic/Bermuda -03:00/-04:00
America/Asuncion -04:00/-03:00 ~ America/Halifax -03:00/-04:00
America/Asuncion -04:00/-03:00 ~ America/Glace_Bay -03:00/-04:00
America/Asuncion -04:00/-03:00 ~ America/Thule -03:00/-04:00
America/Asuncion -04:00/-03:00 ~ America/Goose_Bay -03:00/-04:00
America/Atka -09:00/-10:00 ~ Pacific/Marquesas -09:30/-09:30
Pacific/Marquesas -09:30/-09:30 ~ America/Adak -09:00/-10:00
Pacific/Marquesas -09:30/-09:30 ~ US/Aleutian -09:00/-10:00
like image 150
josejuan Avatar answered Nov 03 '22 03:11

josejuan


tl;dr

To sort ZoneId objects (time zones), you must specify a moment for which you want the offset (ZoneOffset) in effect in each time zone.

Instant instant = Instant.now();
record OffsetForZone( ZoneId zoneId , ZoneOffset offset ) { }
List < OffsetForZone > results =
        ZoneId
                .getAvailableZoneIds()
                .stream()
                .map(
                        ( String zone ) -> new OffsetForZone( ZoneId.of( zone ) , ZoneId.of( zone ).getRules().getOffset( instant ) )
                )
                .sorted(
                        Comparator
                                .comparing( OffsetForZone :: offset ).reversed()
                                .thenComparing( ( OffsetForZone o ) -> o.zoneId.getId() )
                )
                .toList();

Zones sorted by offset in effect at 2021-09-08T08:51:02.939266Z is: [OffsetForZone[zoneId=Etc/GMT+12, offset=-12:00], OffsetForZone[zoneId=Etc/GMT+11, offset=-11:00], OffsetForZone[zoneId=Pacific/Midway, offset=-11:00], OffsetForZone[zoneId=Pacific/Niue, offset=-11:00], …

Time zones cannot be sorted

An offset-from-UTC is merely a number of hours-minutes-seconds, nothing more.

A time zone, in contrast, is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians. So a time zone may have many offsets, only one of which is in effect at any moment.

So it makes no sense to order time zones by offset, unless you specify a particular moment. And even then, many time zones may coincidentally share the same offset at any particular moment.

You asked:

One timezone could be -2:00 related to UTC while another one would be +2:00 for example. Why not consider those as -2:00 < +2:00 and so on?

Because those facts could be true for one moment but not another moment. Those zones may use a different offset on a different date and time.

Code example

Here is some code to sort time zones by their offset in use at a particular moment. We will capture the current moment, as seen in UTC. For that we use the Instant class.

Instant instant = Instant.now() ; 

Get a set of all the time zone identifiers.

Set < String > zones = ZoneId.getAvailableZoneIds();

For each of those zones, we need to determine the current offset. We need to store that info in objects, collected for sorting. In Java 16+, we can use a record to briefly write that class.

record OffsetForZone( ZoneId zoneId , ZoneOffset offset ) { }

Loop all the zone ids, getting the ZoneId for each. With that ZoneId, get the rules for than zone. Ask the rules for offset in effect at our specific moment. Record each ZoneId and is ZoneOffset for that moment in a list.

for ( String zone : zones )
{
    ZoneId zoneId = ZoneId.of( zone );
    ZoneRules rules = zoneId.getRules();
    ZoneOffset offset = rules.getOffset( instant );
    OffsetForZone offsetForZone = new OffsetForZone( zoneId , offset );
    results.add( offsetForZone );
}

Being simply a number of hours-minutes-seconds, the ZoneOffset class implements Comparable. This means we can sort on ZoneOffset, unlike ZoneId.

We want to sort first by the offset. Secondarily, for those zones sharing the same offset in effect at that moment, we want to sort alphabetically by the zone ID.

The Comparator class makes such sorting quite easy, along with the List#sort method.

results.sort(
        Comparator
                .comparing( OffsetForZone :: offset )
                .thenComparing( ( OffsetForZone o ) -> o.zoneId.getId() )
);

If desired, add a .reversed call to sort in opposite direction.

results.sort(
        Comparator
                .comparing( OffsetForZone :: offset ).reversed()
                .thenComparing( ( OffsetForZone o ) -> o.zoneId.getId() )
);

Usually best to return an unmodifiable list.

results = List.copyOf( results ) ;

Dump to console.

System.out.println( "Zones sorted by offset in effect at " + instant + " is: " + results );

When run you will see something like the following. (Abbreviated to fit text limits of Stack Overflow.)

Zones sorted by offset in effect at 2021-09-08T06:40:09.461149Z is: [OffsetForZone[zoneId=Etc/GMT-14, offset=+14:00], OffsetForZone[zoneId=Pacific/Kiritimati, offset=+14:00], OffsetForZone[zoneId=Etc/GMT-13, offset=+13:00], OffsetForZone[zoneId=Pacific/Apia, offset=+13:00], OffsetForZone[zoneId=Pacific/Enderbury, offset=+13:00], OffsetForZone[zoneId=Pacific/Fakaofo, offset=+13:00], OffsetForZone[zoneId=Pacific/Tongatapu, offset=+13:00], OffsetForZone[zoneId=NZ-CHAT, offset=+12:45], OffsetForZone[zoneId=Pacific/Chatham, offset=+12:45], OffsetForZone[zoneId=Antarctica/McMurdo, offset=+12:00], OffsetForZone[zoneId=Antarctica/South_Pole, offset=+12:00], OffsetForZone[zoneId=Asia/Anadyr, offset=+12:00], OffsetForZone[zoneId=Asia/Kamchatka, offset=+12:00], OffsetForZone[zoneId=Etc/GMT-12, offset=+12:00], OffsetForZone[zoneId=Kwajalein, offset=+12:00], OffsetForZone[zoneId=NZ, offset=+12:00], OffsetForZone[zoneId=Pacific/Auckland, offset=+12:00], OffsetForZone[zoneId=Pacific/Fiji, offset=+12:00], OffsetForZone[zoneId=Pacific/Funafuti, offset=+12:00], OffsetForZone[zoneId=Pacific/Kwajalein, offset=+12:00], OffsetForZone[zoneId=Pacific/Majuro, offset=+12:00], OffsetForZone[zoneId=Pacific/Nauru, offset=+12:00], OffsetForZone[zoneId=Pacific/Tarawa, offset=+12:00], OffsetForZone[zoneId=Pacific/Wake, offset=+12:00], OffsetForZone[zoneId=Pacific/Wallis, offset=+12:00], OffsetForZone[zoneId=Antarctica/Casey, offset=+11:00], OffsetForZone[zoneId=Asia/Magadan, offset=+11:00], OffsetForZone[zoneId=Asia/Sakhalin, offset=+11:00], OffsetForZone[zoneId=Asia/Srednekolymsk, offset=+11:00], OffsetForZone[zoneId=Etc/GMT-11, offset=+11:00], OffsetForZone[zoneId=Pacific/Bougainville, offset=+11:00], OffsetForZone[zoneId=Pacific/Efate, offset=+11:00], OffsetForZone[zoneId=Pacific/Guadalcanal, offset=+11:00], OffsetForZone[zoneId=Pacific/Kosrae, offset=+11:00], OffsetForZone[zoneId=Pacific/Norfolk, offset=+11:00], OffsetForZone[zoneId=Pacific/Noumea, offset=+11:00], OffsetForZone[zoneId=Pacific/Pohnpei, offset=+11:00], OffsetForZone[zoneId=Pacific/Ponape, offset=+11:00], OffsetForZone[zoneId=Australia/LHI, offset=+10:30], OffsetForZone[zoneId=Australia/Lord_Howe, offset=+10:30], OffsetForZone[zoneId=Antarctica/DumontDUrville, offset=+10:00], OffsetForZone[zoneId=Antarctica/Macquarie, offset=+10:00], OffsetForZone[zoneId=Asia/Ust-Nera, offset=+10:00], OffsetForZone[zoneId=Asia/Vladivostok, offset=+10:00], OffsetForZone[zoneId=Australia/ACT, offset=+10:00], OffsetForZone[zoneId=Australia/Brisbane, offset=+10:00], OffsetForZone[zoneId=Australia/Canberra, offset=+10:00], OffsetForZone[zoneId=Australia/Currie, offset=+10:00], OffsetForZone[zoneId=Australia/Hobart, offset=+10:00], OffsetForZone[zoneId=Australia/Lindeman, offset=+10:00], OffsetForZone[zoneId=Australia/Melbourne, offset=+10:00], OffsetForZone[zoneId=Australia/NSW, offset=+10:00], OffsetForZone[zoneId=Australia/Queensland, offset=+10:00], OffsetForZone[zoneId=Australia/Sydney, offset=+10:00], OffsetForZone[zoneId=Australia/Tasmania, offset=+10:00], OffsetForZone[zoneId=Australia/Victoria, offset=+10:00], OffsetForZone[zoneId=Etc/GMT-10, offset=+10:00], OffsetForZone[zoneId=Pacific/Chuuk, offset=+10:00], OffsetForZone[zoneId=Pacific/Guam, offset=+10:00], OffsetForZone[zoneId=Pacific/Port_Moresby, offset=+10:00], OffsetForZone[zoneId=Pacific/Saipan, offset=+10:00], OffsetForZone[zoneId=Pacific/Truk, offset=+10:00], OffsetForZone[zoneId=Pacific/Yap, offset=+10:00], OffsetForZone[zoneId=Australia/Adelaide, offset=+09:30], OffsetForZone[zoneId=Australia/Broken_Hill, offset=+09:30], OffsetForZone[zoneId=Australia/Darwin, offset=+09:30], OffsetForZone[zoneId=Australia/North, offset=+09:30], OffsetForZone[zoneId=Australia/South, offset=+09:30], OffsetForZone[zoneId=Australia/Yancowinna, offset=+09:30], OffsetForZone[zoneId=Asia/Chita, offset=+09:00], OffsetForZone[zoneId=Asia/Dili, offset=+09:00], OffsetForZone[zoneId=Asia/Jayapura, offset=+09:00], OffsetForZone[zoneId=Asia/Khandyga, offset=+09:00], OffsetForZone[zoneId=Asia/Pyongyang, offset=+09:00], OffsetForZone[zoneId=Asia/Seoul, offset=+09:00], OffsetForZone[zoneId=Asia/Tokyo, offset=+09:00], OffsetForZone[zoneId=Asia/Yakutsk, offset=+09:00], OffsetForZone[zoneId=Etc/GMT-9, offset=+09:00], OffsetForZone[zoneId=Japan, offset=+09:00], OffsetForZone[zoneId=Pacific/Palau, offset=+09:00], OffsetForZone[zoneId=ROK, offset=+09:00], OffsetForZone[zoneId=Australia/Eucla, offset=+08:45], OffsetForZone[zoneId=Asia/Brunei, offset=+08:00], OffsetForZone[zoneId=Asia/Choibalsan, offset=+08:00], OffsetForZone[zoneId=Asia/Chongqing, offset=+08:00], OffsetForZone[zoneId=Asia/Chungking, offset=+08:00], OffsetForZone[zoneId=Asia/Harbin, offset=+08:00], OffsetForZone[zoneId=Asia/Hong_Kong, offset=+08:00], OffsetForZone[zoneId=Asia/Irkutsk, offset=+08:00], OffsetForZone[zoneId=Asia/Kuala_Lumpur, offset=+08:00], OffsetForZone[zoneId=Asia/Kuching, offset=+08:00], OffsetForZone[zoneId=Asia/Macao, offset=+08:00], OffsetForZone[zoneId=Asia/Macau, offset=+08:00], OffsetForZone[zoneId=Asia/Makassar, offset=+08:00], OffsetForZone[zoneId=Asia/Manila, offset=+08:00], OffsetForZone[zoneId=Asia/Shanghai, offset=+08:00], OffsetForZone[zoneId=Asia/Singapore, offset=+08:00], OffsetForZone[zoneId=Asia/Taipei, offset=+08:00], OffsetForZone[zoneId=Asia/Ujung_Pandang, offset=+08:00], OffsetForZone[zoneId=Asia/Ulaanbaatar, offset=+08:00], OffsetForZone[zoneId=Asia/Ulan_Bator, offset=+08:00], OffsetForZone[zoneId=Australia/Perth, offset=+08:00], OffsetForZone[zoneId=Australia/West, offset=+08:00], OffsetForZone[zoneId=Etc/GMT-8, offset=+08:00], OffsetForZone[zoneId=Hongkong, offset=+08:00], OffsetForZone[zoneId=PRC, offset=+08:00], OffsetForZone[zoneId=Singapore, offset=+08:00], OffsetForZone[zoneId=Antarctica/Davis, offset=+07:00], OffsetForZone[zoneId=Asia/Bangkok, offset=+07:00], OffsetForZone[zoneId=Asia/Barnaul, offset=+07:00], OffsetForZone[zoneId=Asia/Ho_Chi_Minh, offset=+07:00], OffsetForZone[zoneId=Asia/Hovd, offset=+07:00], OffsetForZone[zoneId=Asia/Jakarta, offset=+07:00], OffsetForZone[zoneId=Asia/Krasnoyarsk, offset=+07:00], OffsetForZone[zoneId=Asia/Novokuznetsk, offset=+07:00], OffsetForZone[zoneId=Asia/Novosibirsk, offset=+07:00], OffsetForZone[zoneId=Asia/Phnom_Penh, offset=+07:00], OffsetForZone[zoneId=Asia/Pontianak, offset=+07:00], OffsetForZone[zoneId=Asia/Saigon, offset=+07:00], OffsetForZone[zoneId=Asia/Tomsk, offset=+07:00], OffsetForZone[zoneId=Asia/Vientiane, offset=+07:00], OffsetForZone[zoneId=Etc/GMT-7, offset=+07:00], OffsetForZone[zoneId=Indian/Christmas, offset=+07:00], OffsetForZone[zoneId=Asia/Rangoon, offset=+06:30], OffsetForZone[zoneId=Asia/Yangon, offset=+06:30], OffsetForZone[zoneId=Indian/Cocos, offset=+06:30], OffsetForZone[zoneId=Antarctica/Vostok, offset=+06:00], OffsetForZone[zoneId=Asia/Almaty, offset=+06:00], OffsetForZone[zoneId=Asia/Bishkek, offset=+06:00], OffsetForZone[zoneId=Asia/Dacca, offset=+06:00], OffsetForZone[zoneId=Asia/Dhaka, offset=+06:00], OffsetForZone[zoneId=Asia/Kashgar, offset=+06:00], OffsetForZone[zoneId=Asia/Omsk, offset=+06:00], OffsetForZone[zoneId=Asia/Qostanay, offset=+06:00], OffsetForZone[zoneId=Asia/Thimbu, offset=+06:00], OffsetForZone[zoneId=Asia/Thimphu, offset=+06:00], OffsetForZone[zoneId=Asia/Urumqi, offset=+06:00], OffsetForZone[zoneId=Etc/GMT-6, offset=+06:00], OffsetForZone[zoneId=Indian/Chagos, offset=+06:00], OffsetForZone[zoneId=Asia/Kathmandu, offset=+05:45], OffsetForZone[zoneId=Asia/Katmandu, offset=+05:45], OffsetForZone[zoneId=Asia/Calcutta, offset=+05:30], OffsetForZone[zoneId=Asia/Colombo, offset=+05:30], OffsetForZone[zoneId=Asia/Kolkata, offset=+05:30], OffsetForZone[zoneId=Antarctica/Mawson, offset=+05:00], OffsetForZone[zoneId=Asia/Aqtau, offset=+05:00], OffsetForZone[zoneId=Asia/Aqtobe, offset=+05:00], OffsetForZone[zoneId=Asia/Ashgabat, offset=+05:00], OffsetForZone[zoneId=Asia/Ashkhabad, offset=+05:00], OffsetForZone[zoneId=Asia/Atyrau, offset=+05:00], OffsetForZone[zoneId=Asia/Dushanbe, offset=+05:00], OffsetForZone[zoneId=Asia/Karachi, offset=+05:00], OffsetForZone[zoneId=Asia/Oral, offset=+05:00], OffsetForZone[zoneId=Asia/Qyzylorda, offset=+05:00], OffsetForZone[zoneId=Asia/Samarkand, offset=+05:00], OffsetForZone[zoneId=Asia/Tashkent, offset=+05:00], OffsetForZone[zoneId=Asia/Yekaterinburg, offset=+05:00], OffsetForZone[zoneId=Etc/GMT-5, offset=+05:00], OffsetForZone[zoneId=Indian/Kerguelen, offset=+05:00], OffsetForZone[zoneId=Indian/Maldives, offset=+05:00], OffsetForZone[zoneId=Asia/Kabul, offset=+04:30], OffsetForZone[zoneId=Asia/Tehran, offset=+04:30], OffsetForZone[zoneId=Iran, offset=+04:30], OffsetForZone[zoneId=Asia/Baku, offset=+04:00], OffsetForZone[zoneId=Asia/Dubai, offset=+04:00], OffsetForZone[zoneId=Asia/Muscat, offset=+04:00], OffsetForZone[zoneId=Asia/Tbilisi, offset=+04:00], OffsetForZone[zoneId=Asia/Yerevan, offset=+04:00], OffsetForZone[zoneId=Etc/GMT-4, offset=+04:00], OffsetForZone[zoneId=Europe/Astrakhan, offset=+04:00], OffsetForZone[zoneId=Europe/Samara, offset=+04:00], OffsetForZone[zoneId=Europe/Saratov, offset=+04:00], OffsetForZone[zoneId=Europe/Ulyanovsk, offset=+04:00], OffsetForZone[zoneId=Indian/Mahe, offset=+04:00], OffsetForZone[zoneId=Indian/Mauritius, offset=+04:00], OffsetForZone[zoneId=Indian/Reunion, offset=+04:00], OffsetForZone[zoneId=Africa/Addis_Ababa, offset=+03:00], OffsetForZone[zoneId=Africa/Asmara, offset=+03:00], OffsetForZone[zoneId=Africa/Asmera, offset=+03:00], OffsetForZone[zoneId=Africa/Dar_es_Salaam, offset=+03:00], OffsetForZone[zoneId=Africa/Djibouti, offset=+03:00], OffsetForZone[zoneId=Africa/Kampala, offset=+03:00], OffsetForZone[zoneId=Africa/Mogadishu, offset=+03:00], OffsetForZone[zoneId=Africa/Nairobi, offset=+03:00], OffsetForZone[zoneId=Antarctica/Syowa, offset=+03:00], OffsetForZone[zoneId=Asia/Aden, offset=+03:00], OffsetForZone[zoneId=Asia/Amman, offset=+03:00], OffsetForZone[zoneId=Asia/Baghdad, offset=+03:00], OffsetForZone[zoneId=Asia/Bahrain, offset=+03:00], OffsetForZone[zoneId=Asia/Beirut, offset=+03:00], OffsetForZone[zoneId=Asia/Damascus, offset=+03:00], OffsetForZone[zoneId=Asia/Famagusta, offset=+03:00], OffsetForZone[zoneId=Asia/Gaza, offset=+03:00], OffsetForZone[zoneId=Asia/Hebron, offset=+03:00], OffsetForZone[zoneId=Asia/Istanbul, offset=+03:00], OffsetForZone[zoneId=Asia/Jerusalem, offset=+03:00], OffsetForZone[zoneId=Asia/Kuwait, offset=+03:00], OffsetForZone[zoneId=Asia/Nicosia, offset=+03:00], OffsetForZone[zoneId=Asia/Qatar, offset=+03:00], OffsetForZone[zoneId=Asia/Riyadh, offset=+03:00], OffsetForZone[zoneId=Asia/Tel_Aviv, offset=+03:00], OffsetForZone[zoneId=EET, offset=+03:00], OffsetForZone[zoneId=Etc/GMT-3, offset=+03:00], OffsetForZone[zoneId=Europe/Athens, offset=+03:00], OffsetForZone[zoneId=Europe/Bucharest, offset=+03:00], OffsetForZone[zoneId=Europe/Chisinau, offset=+03:00], OffsetForZone[zoneId=Europe/Helsinki, offset=+03:00], OffsetForZone[zoneId=Europe/Istanbul, offset=+03:00], OffsetForZone[zoneId=Europe/Kiev, offset=+03:00], OffsetForZone[zoneId=Europe/Kirov, offset=+03:00], OffsetForZone[zoneId=Europe/Mariehamn, offset=+03:00], OffsetForZone[zoneId=Europe/Minsk, offset=+03:00], OffsetForZone[zoneId=Europe/Moscow, offset=+03:00], OffsetForZone[zoneId=Europe/Nicosia, offset=+03:00], OffsetForZone[zoneId=Europe/Riga, offset=+03:00], OffsetForZone[zoneId=Europe/Simferopol, offset=+03:00], OffsetForZone[zoneId=Europe/Sofia, offset=+03:00], OffsetForZone[zoneId=Europe/Tallinn, offset=+03:00], OffsetForZone[zoneId=Europe/Tiraspol, offset=+03:00], OffsetForZone[zoneId=Europe/Uzhgorod, offset=+03:00], OffsetForZone[zoneId=Europe/Vilnius, offset=+03:00], OffsetForZone[zoneId=Europe/Volgograd, offset=+03:00], OffsetForZone[zoneId=Europe/Zaporozhye, offset=+03:00], OffsetForZone[zoneId=Indian/Antananarivo, offset=+03:00], OffsetForZone[zoneId=Indian/Comoro, offset=+03:00], OffsetForZone[zoneId=Indian/Mayotte, offset=+03:00], OffsetForZone[zoneId=Israel, offset=+03:00], OffsetForZone[zoneId=Turkey, offset=+03:00], OffsetForZone[zoneId=W-SU, offset=+03:00], OffsetForZone[zoneId=Africa/Blantyre, offset=+02:00], OffsetForZone[zoneId=Africa/Bujumbura, offset=+02:00], OffsetForZone[zoneId=Africa/Cairo, offset=+02:00], OffsetForZone[zoneId=Africa/Ceuta, offset=+02:00], OffsetForZone[zoneId=Africa/Gaborone, offset=+02:00], OffsetForZone[zoneId=Africa/Harare, offset=+02:00], OffsetForZone[zoneId=Africa/Johannesburg, offset=+02:00], OffsetForZone[zoneId=Africa/Juba, offset=+02:00], OffsetForZone[zoneId=Africa/Khartoum, offset=+02:00], OffsetForZone[zoneId=Africa/Kigali, offset=+02:00], OffsetForZone[zoneId=Africa/Lubumbashi, offset=+02:00], OffsetForZone[zoneId=Africa/Lusaka, offset=+02:00], OffsetForZone[zoneId=Africa/Maputo, offset=+02:00], OffsetForZone[zoneId=Africa/Maseru, offset=+02:00], OffsetForZone[zoneId=Africa/Mbabane, offset=+02:00], OffsetForZone[zoneId=Africa/Tripoli, offset=+02:00], OffsetForZone[zoneId=Africa/Windhoek, offset=+02:00], OffsetForZone[zoneId=Antarctica/Troll, offset=+02:00], OffsetForZone[zoneId=Arctic/Longyearbyen, offset=+02:00], OffsetForZone[zoneId=Atlantic/Jan_Mayen, offset=+02:00], OffsetForZone[zoneId=CET, offset=+02:00], OffsetForZone[zoneId=Egypt, offset=+02:00], OffsetForZone[zoneId=Etc/GMT-2, offset=+02:00], OffsetForZone[zoneId=Europe/Amsterdam, offset=+02:00], OffsetForZone[zoneId=Europe/Andorra, offset=+02:00], OffsetForZone[zoneId=Europe/Belgrade, offset=+02:00], OffsetForZone[zoneId=Europe/Berlin, offset=+02:00], OffsetForZone[zoneId=Europe/Bratislava, offset=+02:00], OffsetForZone[zoneId=Europe/Brussels, offset=+02:00], OffsetForZone[zoneId=Europe/Budapest, offset=+02:00], OffsetForZone[zoneId=Europe/Busingen, offset=+02:00], OffsetForZone[zoneId=Europe/Copenhagen, offset=+02:00], OffsetForZone[zoneId=Europe/Gibraltar, offset=+02:00], OffsetForZone[zoneId=Europe/Kaliningrad, offset=+02:00], OffsetForZone[zoneId=Europe/Ljubljana, offset=+02:00], OffsetForZone[zoneId=Europe/Luxembourg, offset=+02:00], OffsetForZone[zoneId=Europe/Madrid, offset=+02:00], OffsetForZone[zoneId=Europe/Malta, offset=+02:00], OffsetForZone[zoneId=Europe/Monaco, offset=+02:00], OffsetForZone[zoneId=Europe/Oslo, offset=+02:00], OffsetForZone[zoneId=Europe/Paris, offset=+02:00], OffsetForZone[zoneId=Europe/Podgorica, offset=+02:00], OffsetForZone[zoneId=Europe/Prague, offset=+02:00], OffsetForZone[zoneId=Europe/Rome, offset=+02:00], OffsetForZone[zoneId=Europe/San_Marino, offset=+02:00], OffsetForZone[zoneId=Europe/Sarajevo, offset=+02:00], OffsetForZone[zoneId=Europe/Skopje, offset=+02:00], OffsetForZone[zoneId=Europe/Stockholm, offset=+02:00], OffsetForZone[zoneId=Europe/Tirane, offset=+02:00], OffsetForZone[zoneId=Europe/Vaduz, offset=+02:00], OffsetForZone[zoneId=Europe/Vatican, offset=+02:00], OffsetForZone[zoneId=Europe/Vienna, offset=+02:00], OffsetForZone[zoneId=Europe/Warsaw, offset=+02:00], OffsetForZone[zoneId=Europe/Zagreb, offset=+02:00], OffsetForZone[zoneId=Europe/Zurich, offset=+02:00], OffsetForZone[zoneId=Libya, offset=+02:00], OffsetForZone[zoneId=MET, offset=+02:00], OffsetForZone[zoneId=Poland, offset=+02:00], OffsetForZone[zoneId=Africa/Algiers, offset=+01:00], OffsetForZone[zoneId=Africa/Bangui, offset=+01:00], OffsetForZone[zoneId=Africa/Brazzaville, offset=+01:00], OffsetForZone[zoneId=Africa/Casablanca, offset=+01:00], OffsetForZone[zoneId=Africa/Douala, offset=+01:00], OffsetForZone[zoneId=Africa/El_Aaiun, offset=+01:00], OffsetForZone[zoneId=Africa/Kinshasa, offset=+01:00], OffsetForZone[zoneId=Africa/Lagos, offset=+01:00], OffsetForZone[zoneId=Africa/Libreville, offset=+01:00], OffsetForZone[zoneId=Africa/Luanda, offset=+01:00], OffsetForZone[zoneId=Africa/Malabo, offset=+01:00], OffsetForZone[zoneId=Africa/Ndjamena, offset=+01:00], OffsetForZone[zoneId=Africa/Niamey, offset=+01:00], OffsetForZone[zoneId=Africa/Porto-Novo, offset=+01:00], OffsetForZone[zoneId=Africa/Tunis, offset=+01:00], OffsetForZone[zoneId=Atlantic/Canary, offset=+01:00], OffsetForZone[zoneId=Atlantic/Faeroe, offset=+01:00], OffsetForZone[zoneId=Atlantic/Faroe, offset=+01:00], OffsetForZone[zoneId=Atlantic/Madeira, offset=+01:00], OffsetForZone[zoneId=Eire, offset=+01:00], OffsetForZone[zoneId=Etc/GMT-1, offset=+01:00], OffsetForZone[zoneId=Europe/Belfast, offset=+01:00], OffsetForZone[zoneId=Europe/Dublin, offset=+01:00], OffsetForZone[zoneId=Europe/Guernsey, offset=+01:00], OffsetForZone[zoneId=Europe/Isle_of_Man, offset=+01:00], OffsetForZone[zoneId=Europe/Jersey, offset=+01:00], OffsetForZone[zoneId=Europe/Lisbon, offset=+01:00], OffsetForZone[zoneId=Europe/London, offset=+01:00], OffsetForZone[zoneId=GB, offset=+01:00], OffsetForZone[zoneId=GB-Eire, offset=+01:00], OffsetForZone[zoneId=Portugal, offset=+01:00], OffsetForZone[zoneId=WET, offset=+01:00], OffsetForZone[zoneId=Africa/Abidjan, offset=Z], OffsetForZone[zoneId=Africa/Accra, offset=Z], OffsetForZone[zoneId=Africa/Bamako, offset=Z], OffsetForZone[zoneId=Africa/Banjul, offset=Z], OffsetForZone[zoneId=Africa/Bissau, offset=Z], OffsetForZone[zoneId=Africa/Conakry, offset=Z], OffsetForZone[zoneId=Africa/Dakar, offset=Z], OffsetForZone[zoneId=Africa/Freetown, offset=Z], OffsetForZone[zoneId=Africa/Lome, offset=Z], OffsetForZone[zoneId=Africa/Monrovia, offset=Z], OffsetForZone[zoneId=Africa/Nouakchott, offset=Z], OffsetForZone[zoneId=Africa/Ouagadougou, offset=Z], OffsetForZone[zoneId=Africa/Sao_Tome, offset=Z], OffsetForZone[zoneId=Africa/Timbuktu, offset=Z], OffsetForZone[zoneId=America/Danmarkshavn, offset=Z], OffsetForZone[zoneId=America/Scoresbysund, offset=Z], OffsetForZone[zoneId=Atlantic/Azores, offset=Z], OffsetForZone[zoneId=Atlantic/Reykjavik, offset=Z], OffsetForZone[zoneId=Atlantic/St_Helena, offset=Z], OffsetForZone[zoneId=Etc/GMT, offset=Z], OffsetForZone[zoneId=Etc/GMT+0, offset=Z], OffsetForZone[zoneId=Etc/GMT-0, offset=Z], OffsetForZone[zoneId=Etc/GMT0, offset=Z], OffsetForZone[zoneId=Etc/Greenwich, offset=Z], OffsetForZone[zoneId=Etc/UCT, offset=Z], OffsetForZone[zoneId=Etc/UTC, offset=Z], OffsetForZone[zoneId=Etc/Universal, offset=Z], OffsetForZone[zoneId=Etc/Zulu, offset=Z], OffsetForZone[zoneId=GMT, offset=Z], OffsetForZone[zoneId=GMT0, offset=Z], OffsetForZone[zoneId=Greenwich, offset=Z], OffsetForZone[zoneId=Iceland, offset=Z], OffsetForZone[zoneId=UCT, offset=Z], OffsetForZone[zoneId=UTC, offset=Z], OffsetForZone[zoneId=Universal, offset=Z], OffsetForZone[zoneId=Zulu, offset=Z], …
like image 45
Basil Bourque Avatar answered Nov 03 '22 02:11

Basil Bourque