在 Java 中将字符串转换为 LocalDateTime

Convert String to LocalDateTime in Java

我有这个字符串

Fri, 07 Aug 2020 18:00:00 +0000

我需要将其转换为 LocalDateTime

我尝试了几种方法:

创建 DateTimeFormatter 并解析字符串

String dateString = "Fri, 07 Aug 2020 18:00:00 +0000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E, dd MMM yyyy HH:mm:ss", Locale.getDefault());
LocalDateTime parsedDate = LocalDateTime.parse(publishedString, formatter);

使用 SimpleDateFormat 将其转换为 Date,然后将 resultDate 转换为 LocalDateTime

String dateString = "Fri, 07 Aug 2020 18:00:00 +0000";
SimpleDateFormat dateFormatter = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z");
Date date = dateFormatter.parse(publishedString);
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

两种解决方案都给出了相同的异常:

java.time.format.DateTimeParseException: Text 'Fri, 07 Aug 2020 18:00:00 +0000' could not be parsed 
at index 0 at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)

如何转换该字符串?

我会说使用 Locale.ROOT 并且不要忘记 DateTimeFormatter 中的 Z class

String dateString = "Fri, 07 Aug 2020 18:00:00 +0000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E, dd MMM yyyy HH:mm:ss Z", Locale.ROOT);
LocalDateTime parsedDate = LocalDateTime.parse(dateString, formatter);

tl;博士

OffsetDateTime.parse( 
    "Fri, 07 Aug 2020 18:00:00 +0000" , 
    DateTimeFormatter.RFC_1123_DATE_TIME 
)

看到这个code run live at IdeOne.com

LocalDateTime是错误的class

您的输入字符串包含 +0000,表示 offset-from-UTC。

所以你不应该使用 LocalDateTime。 class 故意缺少任何时区或偏移量的概念。使用 LocalDateTime,您的字符串 Fri, 07 Aug 2020 18:00:00 +0000 将在 2020 年 8 月 7 日变为 6M,但我们不知道那是日本东京下午 6 点、法国图卢兹下午 6 点还是美国俄亥俄州托莱多下午 6 点— 所有不同的时刻相隔几个小时。

OffsetDateTime

相反,此值应解析为 OffsetDateTime

正在解析

您输入的格式为 RFC 1123。该特定格式在 java.time.

中预定义
String input = "Fri, 07 Aug 2020 18:00:00 +0000";
DateTimeFormatter f = DateTimeFormatter.RFC_1123_DATE_TIME;
OffsetDateTime odt = OffsetDateTime.parse( input , f );

odt.toString(): 2020-08-07T18:00Z

我知道您需要一个 LocalDateTime 用于 API,由于您无法控制的设计问题,您试图在某个时间点使用 LocalDateTime

如果外部合同规定要理解 LocalDateTime 在哪个时区或哪个 UTC 偏移,则 LocalDateTime 可以工作,至少在 99.977% 的情况下。当一些同事程序员没有阅读合同的那一天,你仍然会有一个编程错误等待发生,这是一个我们无法在代码中解决的问题,只能通过良好的评论来尝试缓解。

例如,如果合同上写的是 UTC,那么我们需要确保将时间转换为 UTC。为此,我们需要字符串的偏移量。

    ZoneOffset contractualOffset = ZoneOffset.UTC;
    String stringWeveGot = "Fri, 07 Aug 2020 18:00:00 +0000";
    LocalDateTime convertedDateTime = OffsetDateTime
            .parse(stringWeveGot, DateTimeFormatter.RFC_1123_DATE_TIME)
            .withOffsetSameInstant(contractualOffset)
            .toLocalDateTime();
    System.out.println(convertedDateTime);

输出:

2020-08-07T18:00

如果字符串中的偏移量已经被要求为 0,则您需要验证它是否为 0,否则错误将被忽视并且用户将得到错误的结果。例如:

    OffsetDateTime parsedOdt = OffsetDateTime
            .parse(stringWeveGot, DateTimeFormatter.RFC_1123_DATE_TIME);
    if (! parsedOdt.getOffset().equals(contractualOffset)) {
        throw new IllegalStateException("Offset must be " + contractualOffset
                + ", was " + parsedOdt.getOffset());
    }
    LocalDateTime convertedDateTime = parsedOdt.toLocalDateTime();

如果合同提及某个时区,则转换为该时区。我以Australia/Victoria为例。

    ZoneId contractualZone = ZoneId.of("Australia/Victoria");
    String stringWeveGot = "Fri, 07 Aug 2020 18:00:00 +0000";
    LocalDateTime convertedDateTime = OffsetDateTime
            .parse(stringWeveGot, DateTimeFormatter.RFC_1123_DATE_TIME)
            .atZoneSameInstant(contractualZone)
            .toLocalDateTime();
    System.out.println(convertedDateTime);

2020-08-08T04:00

在时钟向后转动的时间异常情况下,例如在夏令时 (DST) 结束时后退,您会得到不明确的结果。

你的代码出了什么问题?

这里解释了你的异常原因:

  • java DateTimeFormatterBuilder fails on testtime