rzo*_*rzo 49 java simpledateformat java-8 java-9 java-10
我在遗留应用程序中有代码和测试用例,可归纳如下:
@Test
public void testParseDate() throws ParseException {
String toParse = "Mo Aug 18 11:25:26 MESZ +0200 2014";
String pattern = "EEE MMM dd HH:mm:ss z Z yyyy";
DateFormat dateFormatter = new SimpleDateFormat(pattern, Locale.GERMANY);
Date date = dateFormatter.parse(toParse);
//skipped assumptions
}
Run Code Online (Sandbox Code Playgroud)
该测试通过Java 8及以下版本.然而,随着Java 10向上,这导致了一个java.text.ParseException: Unparseable date: "Mo Aug 18 11:25:26 MESZ +0200 2014"
.
备案:另外de_DE
,异常也抛出了语言环境
de_CH
,de_AT
,de_LU
.
我知道使用JDK 9(JEP 252)更改了日期格式.但是,我认为这是破坏向后兼容性的颠覆性变化.摘录:
在JDK 9中,Unicode Consortium的公共区域设置数据存储库(CLDR)数据作为默认区域设置数据启用,因此您可以使用标准区域设置数据而无需任何进一步操作.
在JDK 8中,虽然CLDR区域设置数据与JRE捆绑在一起,但默认情况下不启用它.
使用区域设置敏感服务(如日期,时间和数字格式)的代码可能会使用CLDR区域设置数据生成不同的结果.
添加.
一周的某一天(Mo.
)可以补偿这一点并且测试将通过.但是,这不是旧数据的真正解决方案(以序列化形式,如XML).
检查这个计算器后,似乎行为是故意的德语区域,并且可以通过指定减轻java.locale.providers
与COMPAT
模式.但是,我不喜欢依赖于某些系统属性值的想法有两个原因:
我的问题是:
java.locale.providers
),这可能会在不同的环境中被遗忘(应用程序服务器,独立的jar,... .)?Ole*_*.V. 19
我不是说这是一个很好的解决方案,但似乎是一种方法.
Map<Long, String> dayOfWeekTexts = Map.of(1L, "Mo", 2L, "Di",
3L, "Mi", 4L, "Do", 5L, "Fr", 6L, "Sa", 7L, "So");
Map<Long, String> monthTexts = Map.ofEntries(Map.entry(1L, "Jan"),
Map.entry(2L, "Feb"), Map.entry(3L, "Mär"), Map.entry(4L, "Apr"),
Map.entry(5L, "Mai"), Map.entry(6L, "Jun"), Map.entry(7L, "Jul"),
Map.entry(8L, "Aug"), Map.entry(9L, "Sep"), Map.entry(10L, "Okt"),
Map.entry(11L, "Nov"), Map.entry(12L, "Dez"));
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendText(ChronoField.DAY_OF_WEEK, dayOfWeekTexts)
.appendLiteral(' ')
.appendText(ChronoField.MONTH_OF_YEAR, monthTexts)
.appendPattern(" dd HH:mm:ss z Z yyyy")
.toFormatter(Locale.GERMANY);
String toParse = "Mo Aug 18 11:25:26 MESZ +0200 2014";
OffsetDateTime odt = OffsetDateTime.parse(toParse, formatter);
System.out.println(odt);
ZonedDateTime zdt = ZonedDateTime.parse(toParse, formatter);
System.out.println(zdt);
Run Code Online (Sandbox Code Playgroud)
在我的Oracle JDK 10.0.1上运行的输出:
2014-08-18T11:25:26+02:00
2014-08-18T11:25:26+02:00[Europe/Berlin]
Run Code Online (Sandbox Code Playgroud)
然后,再也没有好的解决方案.
java.time
,现代Java日期和时间API,允许我们指定用于格式化和解析的字段的文本.因此,我将其用于星期和月份,指定与旧COMPAT或JRE语言环境数据一起使用的没有点的缩写.我使用了Java 9 Map.of
并Map.ofEntries
构建了我们需要的地图.如果这也适用于Java 8,你必须找到一些其他方法来填充这两个地图,我相信你这样做.
如果你确实需要一个老式的java.util.Date
(可能在遗留代码库中),请像这样转换:
Date date = Date.from(odt.toInstant());
System.out.println("As legacy Date: " + date);
Run Code Online (Sandbox Code Playgroud)
在我的时区输出(欧洲/哥本哈根,可能与您的大致一致):
As legacy Date: Mon Aug 18 11:25:26 CEST 2014
Run Code Online (Sandbox Code Playgroud)
我想如果那是我,我会考虑这样做:
System.setProperty("java.locale.providers", "COMPAT,CLDR");
因此在任何环境中都不会忘记它.COMPAT语言环境数据自1.0以来一直存在(我相信,至少接近),因此很多代码依赖于它(不仅仅是你的).在Java 9中,名称已从JRE更改为COMPAT.对我而言,这可能听起来像是一个保持数据相当长一段时间的计划.根据早期访问文档,它仍然可以在Java 11(下一个"长期支持"Java版本)中使用,并且没有弃用警告等.如果在将来的Java版本中将其删除,您可能很快就会发现在升级之前可以处理问题. 归档时间: |
|
查看次数: |
2700 次 |
最近记录: |