Java 使用org.threeten.bp.format.DateTimeFormatter解析多个模式 简单版本:

Java 使用org.threeten.bp.format.DateTimeFormatter解析多个模式 简单版本:,java,datetime,json-deserialization,swagger-codegen,threetenbp,Java,Datetime,Json Deserialization,Swagger Codegen,Threetenbp,我需要能够只使用一个org.threeten.bp.format.DateTimeFormatter对象解析两种类型的时间戳字符串 模式1 YYYY-MM-DD HH:MM:ss.SSSS-此代码适用于: DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DD HH:mm:ss.SSSSSS"); System.out.println(dtf.parse("2020-06-30 20:20:42

我需要能够只使用一个org.threeten.bp.format.DateTimeFormatter对象解析两种类型的时间戳字符串

模式1 YYYY-MM-DD HH:MM:ss.SSSS-此代码适用于:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DD HH:mm:ss.SSSSSS");
System.out.println(dtf.parse("2020-06-30 20:20:42.871216"));
模式2 YYYY-MM-DD'T'HH:MM:ss.SSS'Z'-此代码也适用于:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DD'T'HH:mm:ss.SSS'Z'");
System.out.println(dtf.parse("2020-06-30T20:20:42.871Z"));
但是我需要一个对象来解析这两个,这不起作用,很明显lol:

DateTimeFormatter dtf = DateTimeFormatter
        .ofPattern("YYYY-MM-DD HH:mm:ss.SSSSSS")
        .andThisPattern("YYYY-MM-DD'T'HH:mm:ss.SSS'Z'");
System.out.println(dtf.parse("2020-06-30 20:20:42.871216"));
System.out.println(dtf.parse("2020-06-30T20:20:42.871Z"));
我尝试了几件事,这是最新的尝试:

DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
DateTimeFormatter dtf = dtfb
        .appendPattern("YYYY-MM-DD HH:mm:ss.SSSSSS")
        .appendPattern("YYYY-MM-DD'T'HH:mm:ss.SSS'Z'")
        .toFormatter();

System.out.println(dtf.parse("2020-06-30 20:20:42.871216"));
System.out.println(dtf.parse("2020-06-30T20:20:42.871Z"));
但这不起作用。我所做的一切似乎都不允许单个对象解析两种类型

有没有办法做到这一点

更大的背景招摇过市代码: 我有一个使用Java Swagger codegen与web服务交互的应用程序。来自web服务的JSON响应包含两种时间戳格式,请参见上文。在我的应用程序中的某个时刻,我调用JSONdeserialize,它尝试使用可配置的DateTimeFormatter对象。然而,在你打电话之前不可能知道你将使用什么样的时间戳格式

2020-07-06 18:53:45 ERROR PartyContactMethodsControllerEmail:352 - org.threeten.bp.format.DateTimeParseException: Text '2020-07-06 18:53:45.449445' could not be parsed at index 10
    at org.threeten.bp.format.DateTimeFormatter.parseToBuilder(DateTimeFormatter.java:1587)
    at org.threeten.bp.format.DateTimeFormatter.parse(DateTimeFormatter.java:1491)
    at org.threeten.bp.OffsetDateTime.parse(OffsetDateTime.java:359)
    at webservice.com.webapp.invoker.JSON$OffsetDateTimeTypeAdapter.read(JSON.java:183)
    at webservice.com.webapp.invoker.JSON$OffsetDateTimeTypeAdapter.read(JSON.java:1)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
    at com.google.gson.Gson.fromJson(Gson.java:887)
    at com.google.gson.Gson.fromJson(Gson.java:852)
    at com.google.gson.Gson.fromJson(Gson.java:801)
    at webservice.com.webapp.invoker.JSON.deserialize(JSON.java:133)
    at webservice.com.webapp.invoker.ApiClient.deserialize(ApiClient.java:711)
    at webservice.com.webapp.invoker.ApiClient.handleResponse(ApiClient.java:914)
    at webservice.com.webapp.invoker.ApiClient.execute(ApiClient.java:841)
    ...
因此,当desearialize调用发现一种不期望的时间戳格式时,它无法成功解析JSON响应


又是一个原始问题:如何在调用反序列化之前将DateTimeFormatter配置为不阻塞时间戳格式?有没有一种方法可以配置/连接Swagger codegen以适应服务器的响应?

您所问的基本问题是这两种格式无法传递兼容的信息。2020-06-30 20:20:42.871216是一天中没有时区或UTC偏移的日期和时间。它可能表示某个时间点,但我们无法正确地解释它,除非我们知道哪个时区这样做是正确的。另一方面,2020-06-30T20:20:42.871Z中的尾随Z是UTC的零偏移量,因此这里我们得到了提供给我们的信息

在下面的代码片段中,我假设在UTC中也可以理解不带UTC偏移量的格式

    DateTimeFormatter singleFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendPattern("[ ]['T']")
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendPattern("[X]")
            .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
            .toFormatter();

    OffsetDateTime odt1 = OffsetDateTime.parse("2020-06-30 20:20:42.871216", singleFormatter);
    System.out.println(odt1);
    
    OffsetDateTime odt2 = OffsetDateTime.parse("2020-06-30T20:20:42.871Z", singleFormatter);
    System.out.println(odt2);
输出为:


我通过格式模式字符串中的可选元素处理日期和时间之间的空格和T之间的区别。方括号中的任何内容都被认为是可选的,因此[]['T']解析一个可选的空格,后跟一个可选的文本T。小数位数的变化很容易,因为内置的DateTimeFormatter.ISO_LOCAL_TIME可以处理这个问题。这就是我想使用生成器的主要原因:它允许我将其他格式化程序构建到我正在构建的格式化程序中。最后,通过一组新的方括号处理可选偏移。大写的X解析一个偏移量,该偏移量可用Z表示零。因为Z是一个偏移量,所以千万不要使用硬编码的文字Z来解析它,因为这会丢弃偏移量信息。解析偏移量允许我将整个字符串解析为OffsetDateTime。只有在另一种格式没有偏移量的情况下才有可能这样做?对parseDefaulting的调用指定了在不解析任何格式时要使用的偏移量。

您要问的基本问题是这两种格式不能传递兼容的信息。2020-06-30 20:20:42.871216是一天中没有时区或UTC偏移的日期和时间。它可能表示某个时间点,但我们无法正确地解释它,除非我们知道哪个时区这样做是正确的。另一方面,2020-06-30T20:20:42.871Z中的尾随Z是UTC的零偏移量,因此这里我们得到了提供给我们的信息

在下面的代码片段中,我假设在UTC中也可以理解不带UTC偏移量的格式

    DateTimeFormatter singleFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendPattern("[ ]['T']")
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendPattern("[X]")
            .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
            .toFormatter();

    OffsetDateTime odt1 = OffsetDateTime.parse("2020-06-30 20:20:42.871216", singleFormatter);
    System.out.println(odt1);
    
    OffsetDateTime odt2 = OffsetDateTime.parse("2020-06-30T20:20:42.871Z", singleFormatter);
    System.out.println(odt2);
输出为:


我通过格式模式字符串中的可选元素处理日期和时间之间的空格和T之间的区别。方括号中的任何内容都被认为是可选的,因此[]['T']解析一个可选的空格,后跟一个可选的文本T。小数位数的变化很容易,因为内置的DateTimeFormatter.ISO_LOCAL_TIME可以处理这个问题。这就是我想使用生成器的主要原因:它允许我将其他格式化程序构建到我正在构建的格式化程序中。最后,通过一组新的方括号处理可选偏移。大写的X解析一个偏移量,该偏移量可用Z表示零。因为Z是一个偏移量,所以千万不要使用硬编码的文字Z来解析它,因为这会丢弃偏移量信息。解析偏移量允许我将整个字符串解析为OffsetDateTime。只有在另一种格式没有偏移量的情况下才有可能这样做?对parseDefaulting的调用指定在不分析任何内容时使用的偏移量。

顺便问一下,您确定YYYY和DD是正确的格式说明符吗?我希望它们分别是yyyy和dd。顺便问一下,您确定yyyy和dd是正确的格式说明符吗?我希望它们分别是yyyy和dd。