首页 > 解决方案 > 为什么 java.time.ZoneId 没有实现 Comparable 接口?

问题描述

只是出于好奇,为什么我不能比较时区?

例如,一个时区可能是与 UTC 相关的 -2:00,而另一个时区可能是 +2:00。为什么不将它们视为 -2:00 < +2:00 等等?

标签: java

解决方案


由于对Time ZonesZoneId进行编码并且它改变了 UTC 的偏移量,因此没有order

这就是为什么ZoneOffset实现Comparable<ZoneOffset>,因为它是一个固定的偏移量。

(补充说明)

例如:

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

有时的顺序Newfoundland ~ Belem是,-02:30 > -03:00但有时是-03:30 < -03:00

A < B列出偏移顺序从 更改为 的所有(从现在到四年)区域 id 对的简单方法B < A可能是:

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

}

带输出(针对该时间间隔和当前规则)

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

推荐阅读