java - Java 11 在某些情况下无法将 String 转换为 LocalDateTime
问题描述
我在下面有这些代码:
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.time.format.DateTimeParseException: Text '20 Janeiro 2021 00:26' could not be parsed at index 3。
我也有类似的情况,我要转换的字符串中有一个区域,代码是:
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:无法在索引 24 处解析文本“20 Janeiro 2021 00:26”。
这个错误发生在 macOS 上,我还没有在其他操作系统上尝试过。
我不知道这个错误是由于java版本还是其他原因。期待你的答复。非常感谢!
解决方案
热内卢的大J还是小J?
在我看来,有两个错误:一个在您的字符串中,它应该在janeiro中有一个小 j ,另一个在 Java 8 中,它接受您拥有的大写 J。说几十年前我在葡萄牙时只学了几句葡萄牙语
不同语言的月份名称是语言环境数据的一部分。Java 最多可以从四个来源获取其语言环境数据。Java 8 中的默认设置是自 Java 早期版本以来的 Java 内置语言环境数据。从 Java 9 开始,默认值为 CLDR,即 Unicode Common Locale Data Repository。所以在 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
解析 UTC 偏移量
我无法重现您的其他示例。您的getDatePosted
方法在我在 Mac 上的 Oracle jdk-11.0.3 上运行良好并返回2021-08-15T09:00:28
. 我不知道为什么它没有在你的电脑上。
但是,您的代码还有另一个问题:您正在解析为 aLocalDateTime
从而丢弃了时区信息。不要那样做。例如,字符串2021-08-15 09:00:28 (UTC-12:00)
和2021-08-15 09:00:28 (UTC+14:00)
在 tome 中表示非常不同的点,相隔 26 小时,但将被解析为相同的LocalDateTime
. 解析为 aZonedDateTime
以保留时区。如果您需要不同时区的时间(例如您自己的时区),请转换ZonedDateTime
为该时区的 a。LocalDateTime
如果可以通过任何方式避免它,请不要使用它。
解决方法:如果您无法UTC+01:00
将时区解析为工作,则可以使用以下 hack:
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 parsing DayOfWeek in German locale, java8 vs java9
推荐阅读
- pytorch - 使用预训练的 pytorch vgg16 模型及其类进行分类
- r - asotiation 规则,我需要如何为 fpgrowth 转换数据
- azure-stack - Azure Stack 市场产品
- python - 如何填补图像中的孔
- flutter - PageView 在更改页面颤动中进行更改
- vim - 使用 Mac 终端退出 SQL 编辑器
- node.js - 为什么我的 raspberry pi 自托管网站会不一致地停止超过 10 秒?
- c++ - 当我们使用库时,c++ 模板如何工作?
- asp.net-core - 设置时
真的 在 asp.net core 2.2 项目自定义中间件不调用 - android - 将 EditText 转换为整数 (INT)