使用 org.threeten.bp.format.DateTimeFormatter 解析多个模式

Parse multiple patterns using org.threeten.bp.format.DateTimeFormatter

提问人:ryvantage 提问时间:7/7/2020 最后编辑:Anonymousryvantage 更新时间:7/8/2020 访问量:1056

问:

简单版:

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

模式 1 (“YYYY-MM-DD HH:mm:ss.SSSSSS“ -- 此代码有效):

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"));

但是我需要单个对象来解析两者(这不起作用,显然哈哈):

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"));

但这没有用。我所做的任何事情似乎都不允许单个对象解析两种类型。

有没有办法做到这一点?

更大的上下文 (Swagger codegen):

我有一个使用 Java Swagger codegen 与 Web 服务交互的应用程序。来自 Web 服务的 JSON 响应包含两种时间戳格式(见上文)。在我的应用程序中的某个时刻,我调用 JSON#deserialize,它尝试使用(可配置的)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)
    ...

因此,当调用找到它不需要的时间戳格式时,它无法成功解析 JSON 响应。desearialize

又是原始问题:如何将 DateTimeFormatter 配置为(在调用 deserialize 之前)不会阻塞时间戳格式?有没有办法配置/与 Swagger codegen 交互以适应服务器的响应?

java 日期时间 json 反序列化 swagger-codegen threetenbp

评论

1赞 MC Emperor 7/8/2020
顺便说一句,您确定并且是正确的格式说明符吗?我希望他们分别是和。YYYYDDyyyydd

答:

3赞 Anonymous 7/8/2020 #1

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

在下面的代码片段中,我假设没有 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);

输出为:

2020-06-30T20:20:42.871216Z
2020-06-30T20:20:42.871Z

我通过格式模式字符串中的可选元素处理日期和时间之间的空格和日期和时间之间的区别。括在方括号中的任何内容都被视为可选,因此解析可选空格,后跟可选文本。小数点数的变化很容易,因为内置功能可以处理这个问题。这是我想使用构建器的主要原因:它允许我在我正在构建的格式化程序中构建其他格式化程序。最后,通过一组新的方括号处理可选偏移量。大写分析可能以零形式给出的偏移量。由于是偏移量,因此绝不能使用硬编码的文字来解析它,因为这会丢弃偏移量信息。解析偏移量允许我将整个字符串解析为 .只有当其他格式没有偏移量时,这怎么可能呢?调用指定在未分析任何偏移量时要使用的偏移量。T[ ]['T']TDateTimeFormatter.ISO_LOCAL_TIMEXZZZOffsetDateTimeparseDefaulting()