ZonedDateTime.parse() 在 Windows 中对于完全相同的字符串失败,但在 Mac 和 Linux 中有效

问题描述

以下 UnitTest 在 Windows 机器(Java 11.0.9)中通过 IntelliJ IDE 执行时失败,但在具有相同 Java 版本的 Mac 或 Linux 机器上执行时通过。

@Test
public void rfc1123JaveTimeUtilParsing(){
    final String rfc1123Pattern = "EEE,dd MMM yyyy HH:mm:ss z";
    final String responseTimeStamp = "Mon,14 Dec 2020 20:34:37 GMT";

    DateTimeFormatter javaTimeDateTimeFormatter = DateTimeFormatter.ofPattern(rfc1123Pattern);
    zoneddatetime javaFinalTime = zoneddatetime.parse(responseTimeStamp,javaTimeDateTimeFormatter);
    Assert.assertNotNull(javaFinalTime);
}

对于 Windows,结果是以下异常:

java.time.format.DateTimeParseException:无法在索引 0 处解析文本“Mon,14 Dec 2020 20:34:37 GMT”

解决方法

切勿在没有 DateTimeFormatter 的情况下使用 Locale

由于给定的日期时间是英文的,您应该将 DateTimeFormatterLocale.ENGLISH 一起使用。

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        final String responseTimeStamp = "Mon,14 Dec 2020 20:34:37 GMT";
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE,dd MMM yyyy HH:mm:ss z",Locale.ENGLISH);
        ZonedDateTime zdt = ZonedDateTime.parse(responseTimeStamp,dtf);
        System.out.println(zdt);
    }
}

输出:

2020-12-14T20:34:37Z[GMT]

默认情况下,DateTimeFormatter#ofPattern 使用 JVM 在启动时根据宿主环境设置的 default FORMAT locale。我试图通过以下演示来说明问题:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        final String responseTimeStamp = "Mon,14 Dec 2020 20:34:37 GMT";
        DateTimeFormatter dtfWithDefaultLocale = null;

        System.out.println("JVM's Locale: " + Locale.getDefault());
        // DateTimeFormatter with the default Locale
        dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE,dd MMM yyyy HH:mm:ss z");
        System.out.println("DateTimeFormatter's Locale: " + dtfWithDefaultLocale.getLocale());
        System.out.println(
                "Parsed with JVM's default locale: " + ZonedDateTime.parse(responseTimeStamp,dtfWithDefaultLocale));

        // DateTimeFormatter with Locale.ENGLISH explicitly (recommended)
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE,dtf);
        System.out.println("Parsed with Locale.ENGLISH: " + zdt);

        // Setting the JVM's default locale to Locale.FRANCE
        Locale.setDefault(Locale.FRANCE);
        System.out.println("JVM's Locale: " + Locale.getDefault());
        // DateTimeFormatter with the default Locale
        dtfWithDefaultLocale = DateTimeFormatter.ofPattern("EEE,dtfWithDefaultLocale));
    }
}

输出:

JVM's Locale: en_GB
DateTimeFormatter's Locale: en_GB
Parsed with JVM's default locale: 2020-12-14T20:34:37Z[GMT]
Parsed with Locale.ENGLISH: 2020-12-14T20:34:37Z[GMT]
JVM's Locale: fr_FR
DateTimeFormatter's Locale: fr_FR
Exception in thread "main" java.time.format.DateTimeParseException: Text 'Mon,14 Dec 2020 20:34:37 GMT' could not be parsed at index 0
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.ZonedDateTime.parse(ZonedDateTime.java:598)
    at Main.main(Main.java:29)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...