使用 RFC_1123_DATE_TIME 解析日期时出错 (Java)

Error parsing Date with RFC_1123_DATE_TIME (Java)

提问人:Paolo Mossini 提问时间:10/4/2023 更新时间:10/5/2023 访问量:77

问:

我使用这段代码从 String 中提取一个 Date 对象:

Date.from(ZonedDateTime.parse(exchange.getIn().getHeader("Date").toString(), DateTimeFormatter.RFC_1123_DATE_TIME).toInstant());

但是当字符串是这样的时,我有错误:Tue, 26 Nov 2019 09:00:01 +0100 (CET)

如何解析这种获取 Date 对象的字符串?我是否需要使用另一个 DateTimeFormatter?

Java 、日期、时间、格式化程序

评论

1赞 Anonymous 10/4/2023
你确定你需要一个老式的吗?如果你不是,我建议你坚持(或)。DateZonedDateTimeOffsetDateTime
0赞 Anonymous 10/4/2023
如果我没记错的话,阅读 RFC,有许多变体没有涵盖。DateTimeFormatter.RFC_1123_DATE_TIME
0赞 Anonymous 10/5/2023
如果我正确理解了 RFC 1123 和 RFC 822,括号中的所有内容都是针对人类的注释,应该被计算机忽略。在您的情况下,.如果注释总是出现在末尾,您可以尽可能多地解析字符串并忽略其余部分:。这会产生 .(CET)OffsetDateTime.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse("Tue, 26 Nov 2019 09:00:01 +0100 (CET)", new ParsePosition(0)))2019-11-26T09:00:01+01:00

答:

3赞 Vindurrin 10/4/2023 #1

是的,您可以使用自定义来解析格式为“Tue, 26 Nov 2019 09:00:01 +0100 (CET)”的字符串。您提供的格式在括号中包含其他信息,这不是标准 RFC 1123 格式的一部分。DateTimeFormatter

下面是一个示例,说明您可能有一些代码来使用自定义来处理这种情况:DateTimeFormatter

import java.time.*;
import java.time.format.*;
import java.util.*;

String dateString = "Tue, 26 Nov 2019 09:00:01 +0100 (CET)";

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z (zzz)");
ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateString, formatter);
Instant instant = zonedDateTime.toInstant();
Date date = Date.from(instant);

这定义了一个与格式“EEE, d MMM yyyy HH:mm:ss Z (zzz)”匹配的自定义。DateTimeFormatter

  • EEE:星期几
  • D:月份中的某一天
  • MMM:缩写月份名称
  • yyyy:年
  • HH:小时
  • mm:分钟
  • ss:秒
  • Z:时区偏移量
  • zzz:时区缩写

之后,使用格式化程序进行解析,返回一个对象。获取 from 并将其转换回 .这应该会成功解析您提供的字符串,并通过对象进行解析。dateStringZonedDateTimeInstantZonedDateTimeDateDate

示例 Java 类

import java.time.*;
import java.time.format.*;
import java.util.*;

public class DateTest{
    public static void main(String[] args) {
        String dateString = "Tue, 26 Nov 2019 09:00:01 +0100 (CET)";

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z (zzz)");
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateString, formatter);
        Instant instant = zonedDateTime.toInstant();
        Date date = Date.from(instant);

        System.out.println(date);
    }
}

给定字符串:“Tue, 26 Nov 2019 09:00:01 +0100 (CET)” 此程序打印:Tue Nov 26 03:00:01 EST 2019。

也许我不需要指定解析,因为我的安装已经设置为英语语言环境,但您可以尝试解析器末尾的 Locale.ROOT 参数。

评论

0赞 Paolo Mossini 10/4/2023
我试过了,但你发布的代码给了我Text 'Tue, 26 Nov 2019 09:00:01 +0100 (CET)' could not be parsed at index 0
0赞 Anonymous 10/4/2023
为了进行验证,我还将分别解析为一个 ,它将使用偏移量,以及一个 ,它将使用时区缩写,并检查两个解析的日期时间的偏移量是否匹配。OffsetDateTimeZonedDateTime
2赞 Rob Spoor 10/4/2023 #2

根据 RFC 1123 第 5.2.14 节和 RFC 822 第 5 节,不应该存在。区域应为区域 () 或偏移量 (),但不能同时为两者。但是,RFC_1123_DATE_TIME提到了这一点:(CET)CET+0100

这将返回一个不可变的格式化程序,能够格式化和解析大多数 RFC-1123 格式。RFC-1123 更新了 RFC-822,将年份从两位数更改为四位数。此实现需要四位数的年份。此实现也不处理北美或军事区名称,仅处理“GMT”和抵消金额。

换言之,除非时区是 ,否则仅支持偏移量。GMT

如果您仍然需要支持日期,例如您给出的示例,则需要创建自己的实例。使用 a 时,您可以包括可选部件DateTimeFormatterDateTimeFormatterBuilder

编辑:这是您可以使用的格式化程序:

new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.RFC_1123_DATE_TIME)
        .appendOptional(DateTimeFormatter.ofPattern(" (z)"))
        .toFormatter(Locale.ROOT)