具有lnnal且没有分隔符的DateTimeFormatter模式不起作用

时间:2016-08-25 16:10:46

标签: java java-time

DateTimeFormatter.ofPattern生成的解析器表现出以下有趣的行为,这使我无法编写模式来解析像20150100这样的字符串:

System.out.println(DateTimeFormatter.ofPattern("yyyyMM").parse("201501", YearMonth::from)); // works
System.out.println(DateTimeFormatter.ofPattern("yyyyMM'aa'").parse("201501aa", YearMonth::from)); // works
System.out.println(DateTimeFormatter.ofPattern("yyyyMM'00'").parse("20150100", YearMonth::from));
// java.time.format.DateTimeParseException: Text '20150100' could not be parsed at index 0

我对代码进行了调试,似乎问题是由字段末尾解析超出字符串结尾引起的(三个y的最大宽度和更多值总是为19)。但是,我不明白如何在没有'00'文字的情况下对该模式起作用。

有没有办法解决这个问题,因为必须使用格式化程序构建器?

编辑:

由于下面的Jarrod证实了它的错误,我做了更多谷歌搜索并最终找到了错误报告:

testFailureIgnore

same

两者都只在Java 9中修复......

2 个答案:

答案 0 :(得分:4)

DateTimePrinterParser

中存在错误

我一步一步地调试它,显然你不能将数字作为文字。类似的测试代码证明了这一点,如果你逐步调试到DateTimeFormatterBuilder.parse()方法,你可以看到它做错了什么。

显然Value(YearOfEra,4,19,EXCEEDS_PAD)解析器会消耗他们停止的00,如果这些数字不是,因为它正在寻找4到{{1}的数字数字长。 19中嵌入的DateTimeFormatter是错误的。

如果你输入一个像DateTimeParseContext这样的非数字字符,那么数字文字就不会有。

这两个都失败了:

xx
  

线程中的异常" main" java.text.ParseException:无法解析的日期:   " 20150100"在java.text.DateFormat.parse(DateFormat.java:366)

final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM'00'");
System.out.println(sdf.parse("20150100"));
  

线程中的异常" main" java.time.format.DateTimeParseException:   文字' 20150100'无法在索引0处解析   java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)     在   java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)

这两个都成功了:

final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMM'00'");
System.out.println(dateTimeFormatter.parse("20150100", YearMonth::from));
  

2015年1月1日00:00:00美国东部时间

final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM'xx'");
System.out.println(sdf.parse("201501xx"));
  

2015-01

答案 1 :(得分:0)

如果您不介意使用第三方库,那么您可以尝试我的库Time4J,其最新版本v4.18可以按照您的意愿行事:

YearMonth

顺便说一下,JDK-bug-log的链接与你的问题没有关系。这些问题仅描述在小数秒的上下文中应用相邻数字解析时的问题。虽然这个问题将通过Java-9修复,但问题不会解决。也许你想在那里开一个新问题?但我怀疑甲骨文是否会将其视为错误。它是由Oracle分发的任何库直到现在都不支持的新功能。 JSR-310(也就是java.time-package)中不希望带有(前导)数字的文字参与相邻值解析(而calendarMonth.toTemporalAccessor()也不会)。

旁注:Time4J不仅仅是对这个细节(数字文字)的回答,而且通常在解析时提供更好的性能,并且由于很多转换方法可以与JSR-310并行使用。例如:要实现let entity = Person() if let name = person["name"] as? String { entity.name = name } if let gender = person["gender"] as? String { entity.gender = gender } if let age = person["age"] as? Int { entity.age = age } 的实例,只需在解析结果上调用{{1}}。