【问题标题】:How to format timezone having shortname Id and longName?如何格式化具有短名称 ID 和长名称的时区?
【发布时间】:2018-09-02 11:09:41
【问题描述】:

我有timezone = "[PST -08:00] America/Los Angeles (Pacific Standard Time)" 格式。我有time["03:00 pm"]date[2018/4/22]。我需要检查当前当地时间是否少于 12 小时。

joda DateTimeZone 不接受此 ID [DateTimeZone.forID("[PST -08:00] America/Los Angeles (Pacific Standard Time)"]

有什么选择吗?

我在这里只寻找一个时区选项。如何将时区字符串干净地转换为时区?

【问题讨论】:

  • 当你在标题中说“格式”时,我认为你的意思是“解析”?

标签: java timezone jodatime timezone-offset


【解决方案1】:

您应该只使用IANA's zone names,格式为Continent/Region。在这种情况下,您应该使用:

DateTimeZone.forID("America/Los_Angeles");

请注意,名称是“Los_Angeles”,而不是“Los Angeles”(在 Los 之间有一个_ 而不是空格安吉利斯)。

您可以通过循环通过DateTimeZone.getAvailableIDs()返回的集合来检查所有可用的名称:

for (String zoneName : DateTimeZone.getAvailableIDs()) {
    System.out.println(zoneName);
}

在您的具体情况下,您应该解析您的字符串(正如 Georg 的回答所解释的那样)或将其映射到有效的 IANA 名称:

Map<String, String> names = new HashMap<String, String>();
names.put("[PST -08:00] America/Los Angeles (Pacific Standard Time)", "America/Los_Angeles");

或者使用其他一些逻辑,例如:

if (timezoneName.contains("Los Angeles")) {
    // use America/Los_Angeles
}

【讨论】:

    【解决方案2】:

    您必须决定是否要解释多头或空头偏移。我选择了长偏移量,因为您可以从长名称“America/Los_Angeles”创建一个 ZoneId。 ZoneId 然后查询 IANA 时区数据库 - 请参阅 spec。此测试用例从给定模式中提取名称。

    import org.junit.Test;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.util.Date;
    
    public class Zone {
    
        @Test
        public void zoneId() throws ParseException {
            String zoneName = "[PST -08:00] America/Los Angeles (Pacific Standard Time)";
            String time = "03:00 pm";
            String dateString = "2018/4/22";
    
            String americaLosAngelesPST = zoneName.substring(zoneName.indexOf("]") + 2, zoneName.length());
            String americaLosAngeles = americaLosAngelesPST.substring(0, americaLosAngelesPST.indexOf("(") - 1).replace(" ", "_");
            ZoneId zone = ZoneId.of(americaLosAngeles);
    
            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy/MM/dd KK:mm a");
            Date parsedDateTime = inputFormat.parse(dateString + " " + time);
    
            ZonedDateTime inputZonedDateTime = parsedDateTime.toInstant().atZone(zone);
    
            // compare with ZonedDateTime.now()
        }
    
    }
    

    【讨论】:

    • 感谢乔治的回复。除了 parsing(substring) zoneName 还有其他方法吗?我希望我能避免这种情况。
    • 不客气。我不知道其他方法。由于输入有些多余,因此有必要进行子串化。例如。您想使用 PST 还是太平洋标准时区名称?你必须做出决定。此外,绝对有必要以某种方式解析 zonename。作为
    • 请不要教年轻人使用早已过时且臭名昭著的SimpleDateFormat类。至少不是第一选择。而且不是没有任何保留。尤其是在已经使用现代 Java 日期和时间 API java.time 时。它使用起来非常好用,并且拥有您需要的所有功能。
    【解决方案3】:

    还有一个java.time 答案。我去-08:00

        String offsetString = timezone.replaceFirst("\\[[^ ]+ ([+-]\\d{2}:\\d{2})\\].*", "$1");
        ZoneOffset offset = ZoneOffset.of(offsetString);
    

    这给出了-08:00 的偏移量。如果您确实需要时区,我喜欢其他人会选择美国/洛杉矶,这是明确的,而三和四字母缩写不标准化,通常模棱两可且通常不是真正的时区。例如,PST 可能表示太平洋标准时间、菲律宾标准时间或皮特凯恩标准时间。但是,要确定时间是否在当地时间中午 12 点之前,偏移量就足够了,并且更易于解析和使用。

    有趣的是,您的整个时区字符串可以被 DateTimeFormatter.ofPattern("'['zzz xxx']' VV (zzzz)", Locale.US) 解析 如果不是,因为时区以 America/Los Angeles 的形式给出,城市名称中有一个空格。 IANA 时区 ID 有一个下划线。正因为如此,我需要在解析之前对字符串进行一些操作。然后我一路走下去,只取出需要的偏移量。

    Joda-Time 处于维护模式,预计不会有重大改进,他们的开发团队建议迁移到 java.time。不太了解 Joda-Time,我想如果您愿意,可以将我的回答翻译成 Joda-Time。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多