使用Java查找区域的标准时间名称

使用Java查找区域的标准时间名称,java,java-8,java-time,Java,Java 8,Java Time,有没有办法找到时区下的标准时间, 比如说 America/New_York and America/NewJersey -> EST 我正在开发一个REST服务,其中请求将以基于地区的时区(美国/新泽西)作为参数,我需要找到它所处的标准时间,并将其传递给只接受3位数时区(EST/MST/CST/AET)的遗留API 我使用的是Java8,我检查了TimeAPI,但它没有任何这样的特性/功能。作为一种解决方法,我可以在文件或数据库中创建映射,但我只想知道是否有其他人面临此问题,以及是否有任

有没有办法找到时区下的标准时间, 比如说

America/New_York and America/NewJersey -> EST
我正在开发一个REST服务,其中请求将以基于地区的时区(美国/新泽西)作为参数,我需要找到它所处的标准时间,并将其传递给只接受3位数时区(EST/MST/CST/AET)的遗留API


我使用的是Java8,我检查了TimeAPI,但它没有任何这样的特性/功能。作为一种解决方法,我可以在文件或数据库中创建映射,但我只想知道是否有其他人面临此问题,以及是否有任何干净的解决方案。

如果我理解正确,主要要求是具有一些特定的三字母缩写,这些缩写是您无法控制的API所需要的。例如:

    printAbbreviation("Asia/Shanghai");
  • 东部标准时间为EST(可能是北美东部标准时间?),东部时间为ET
  • 另一方面,AET表示澳大利亚东部时间,而不是AEST表示澳大利亚东部标准时间(也不是EST表示东部标准时间,尽管我读到EST在澳大利亚也被用作缩写)
在我看来,Java知道的时区缩写(来自CLDR或您使用的语言环境数据提供者)与API所需的缩写之间似乎没有系统的对应关系。另外一个问题是,三个字母的时区缩写常常模棱两可,因此我怀疑有许多时区您的遗留API根本无法识别(或者它需要一些模糊的本族语缩写,我们几乎没有机会猜到)

方法有两种:

  • Deadpool早就在一篇评论中提出了一种安全但又间接且费劲的方法:构建并保持所需缩写的映射
  • 看看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)));
    }
    
    因此,我们使用它:

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

    我不认为这是一个干净的解决方案。我特别担心的是,该方法会产生一个错误的结果,而您的API对该结果的解释与预期的不同,并且没有人会注意到它反过来会产生一个错误的结果,或者直到为时已晚。例如:

        printAbbreviation("Asia/Shanghai");
    

    这里CST代表中国标准时间,但我猜您的API会将其理解为北美中部标准时间。我们真的不应该依赖三个字母的时区缩写。它们是模棱两可的,可能更多的时候是模棱两可的。正如这个问题所显示的,它们不是标准化的。

    如果我理解正确,主要要求是要有一些特定的三个字母的缩写,这些缩写是您无法控制的API所需要的。例如:

        printAbbreviation("Asia/Shanghai");
    
    • 东部标准时间为EST(可能是北美东部标准时间?),东部时间为ET
    • 另一方面,AET表示澳大利亚东部时间,而不是AEST表示澳大利亚东部标准时间(也不是EST表示东部标准时间,尽管我读到EST在澳大利亚也被用作缩写)
    在我看来,Java知道的时区缩写(来自CLDR或您使用的语言环境数据提供者)与API所需的缩写之间似乎没有系统的对应关系。另外一个问题是,三个字母的时区缩写常常模棱两可,因此我怀疑有许多时区您的遗留API根本无法识别(或者它需要一些模糊的本族语缩写,我们几乎没有机会猜到)

    方法有两种:

  • Deadpool早就在一篇评论中提出了一种安全但又间接且费劲的方法:构建并保持所需缩写的映射
  • 看看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)));
    }
    
    因此,我们使用它:

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

    我不认为这是一个干净的解决方案。我特别担心的是,该方法会产生一个错误的结果,而您的API对该结果的解释与预期的不同,并且没有人会注意到它反过来会产生一个错误的结果,或者直到为时已晚。例如:

        printAbbreviation("Asia/Shanghai");
    

    这里CST代表中国标准时间,但我猜您的API会将其理解为北美中部标准时间。我们真的不应该依赖三个字母的时区缩写。它们是模棱两可的,可能更多的时候是模棱两可的。正如这个问题所显示的,它们不是标准化的。

    看起来你必须自己做@OleV.V。您的解决方案似乎很好,但一些时区未被识别,例如,我得到的是AET而不是AET,遗留系统期望的是AET,这不是因为DST,而是Java时区本身没有三个数字。您似乎必须自己做@OleV.V。您的解决方案似乎不错,但有些时区未被识别,例如,我使用的是AET而不是AET,legacy system期望的是AET,这不是因为DST,而是Java时区本身没有三个数字我尝试过使用这种方法,但缺少几个时区,因此,我深入研究了遗留API并找到了一种传递时区的方法,因为这是Java中的最佳解决方案,我接受这个答案,因为我尝试过使用这种方法,但很少遗漏TIMZONE,所以我深入研究了遗留API并找到了一种传递时区的方法,因为这是optim