当前位置: 首页 > 知识库问答 >
问题:

Java 11在某些情况下无法将字符串转换为LocalDateTime

宰父霖
2023-03-14

我有以下代码:

private void convertStringDatePosted() {
    String stringDatePosted = "20 Janeiro 2021 00:26";
    Locale locale = new Locale("pt", "MZ");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy HH:mm").withLocale(locale);
    LocalDateTime aa = LocalDateTime.parse(stringDatePosted, formatter);
    System.out.println(aa);
}

当我用java 8运行代码时,它可以工作。但对于java 11,它抛出了一个例外:java。时间总体安排DateTimeParseException:无法在索引3处分析文本“20 Janeiro 2021 00:26”。

我也有类似的情况,我要转换的字符串中有一个区域,代码是:

protected LocalDateTime getDatePosted() {
    String dateScraped = "2021-08-15 09:00:28 (UTC+01:00)";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss (z)");
    return LocalDateTime.parse(dateScraped, formatter);
}

如果使用java 8运行,它仍然有效,但使用java 11则不行。异常是:java.time.format.DateTimeParseException:文本'20 Janeiro 2021 00:26'无法在索引24处解析。

这个错误发生在macOS上,我还没有尝试其他操作系统

我不知道这个错误是由于java版本还是其他原因。期待您的回复。非常感谢!

共有1个答案

郎嘉树
2023-03-14

在我看来,有两个bug:一个在字符串中,在janeiro中应该有一个小j;另一个在Java 8中,它接受您的大写j。几十年前我在葡萄牙的时候只学了几个葡萄牙语单词

不同语言的月份名称是区域设置数据的一部分。Java最多可以从四个源获取其语言环境数据。Java 8中的默认值是Java早期版本以来的Java内置语言环境数据。在Java 9中,默认值是CLDR,即Unicode公共语言环境数据存储库。因此,在Java 8中,Java自己的语言环境数据有大写的J。CLDR也可以通过系统属性在Java 8中使用,它有一个小J。一个有趣的观察结果是,当我指示Java 11使用Java自己的语言环境数据时,它也显示了小J。Java 8的错误已经修复。

有许多可能的解决方案。一种是指示格式化程序在解析时不要考虑大小写:

    String stringDatePosted = "20 Janeiro 2021 00:26";
    Locale locale = new Locale("pt", "MZ");
    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .appendPattern("d MMMM yyyy HH:mm")
            .toFormatter(locale);
    LocalDateTime aa = LocalDateTime.parse(stringDatePosted, formatter);
    System.out.println(aa);

输出为:

2021-01-20T00:26

我无法复制你的另一个例子。您的方法在Mac上的my Oracle jdk-11.0.3上运行良好,并返回2021 08-15T09:00:28。我不知道为什么你的电脑上没有。

但是,您的代码还有另一个问题:您正在解析为LocalDateTime,从而丢弃了时区信息。不要那样做。例如,字符串2021 08月15日09:00:28(UTC-12:00)2021 08月15日09:00:28(UTC 14:00)表示时间段中非常不同的点,相隔26小时,但将被解析为相同的LocalDateTime。解析为ZonedDateTime以保留时区。如果您需要不同时区(如您自己的时区)中的时间,请转换为该时区中的分区DateTime。如果可以通过任何方式避免,请不要使用LocalDateTime。

解决方法:如果您无法将UTC 01:00作为时区进行解析,则使用以下黑客操作:

protected OffsetDateTime getDatePosted() {
    String dateScraped = "2021-08-15 09:00:28 (UTC+01:00)";
    DateTimeFormatter formatter = DateTimeFormatter
            .ofPattern("yyyy-MM-dd HH:mm:ss ('UTC'xxx)", Locale.ROOT);
    return OffsetDateTime.parse(dateScraped, formatter);
}

现在该方法返回2021-08-15T09:00:28 01:00。您还注意到UTC偏移量已被保留。

有关不同Java版本中语言环境数据的更多信息的相关问题:JDK dateformatter解析德语语言环境中的DayOfWeek,java8 vs java9

 类似资料:
  • 问题内容: 您如何将此String转换为gson.JsonArray? 这是我的代码: 这是将这个Collections字符串转换为JSonArray的方法吗? 问题答案: 要在JSON数组中包含字符串值,必须记住在Java程序中用反斜杠转义双引号。请参见下面的声明。 您在main()方法中的代码可以正常工作。以下只是对main()方法中的代码的微小修改。 最后,请记住在语句“ com.googl

  • 我将XML作为字符串传递给一个方法,并再次将其转换为XML来完成我的工作。 其正常工作正常,但当出现特殊字符时,如<代码> 我的XML字符串: 我的代码是: 错误: “=”是意外标记。预期标记为“;”。第1行,位置150。 完全错误为: 系统Xml。XmlException未由用户代码处理HResult=-2146232000消息=“=”是意外令牌。预期标记为“;”。第1行,位置150。源=系统。

  • 问题内容: 我有一个android客户端,可通过REST风格的端点和JSON与服务器进行通信。因此,我需要先检索完整的服务器响应,然后再将其转换为哈希。我有以下代码可以做到这一点(可以在某个地方的互联网上找到): 该代码在大多数情况下有效,但是我在行中看到OutOfMemory异常的客户端发生崩溃的报告: 完整的堆栈跟踪为: 我的问题:除了从服务器发送较小的数据块外,还有什么方法可以解决此问题?

  • 问题内容: 我正在编写一些代码,并且我需要它来捕获参数并将它们传递给 我(我想要它的默认行为,编写由空格分隔并后跟换行符的参数)。但是它需要而返回。 这是代码示例: 这将返回以下错误: 这是一个错误吗?不应该接受 任何 数组吗?顺便说一句,我也尝试这样做: 但出现以下错误: 有“解决方案”解决方法吗? 问题答案: 这不是错误。需要一个类型。这意味着它必须是值的切片,而不是“任何切片”。为了转换切片

  • 问题内容: 我正在运行以下python脚本: 但是我得到了类似的错误: 我对此感到困惑。当我在交互式部分中仅尝试一行时,而不是使用脚本进行for循环时: 它运作良好。 有人可以解释一下吗?谢谢。 问题答案: 显然,您的某些行没有有效的float数据,特别是某些行的文本无法转换为float。 当您在交互式提示中尝试它时,您仅尝试第一行,因此最好的方法是在出现此错误的地方打印行,您将知道错误的行,例如

  • 问题内容: 我有一个字符串,是这样的:。 我想将其转换为列表。我知道我可以使用eval(string)来获取列表,但是eval令我感到恐惧,因为它可能会造成灾难(并且因为我可以获取非列表作为有效输出)。还有另一种更安全的方式将此字符串转换为列表吗?我知道这是一个列表,所有不是列表的数据都是无效数据(应该检查和/或抛出错误)。 问题答案: 如果您坚持要这样做,可以使用ast.literal_eval