由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证实了它的错误,我做了更多谷歌搜索并最终找到了错误报告:
两者都只在Java 9中修复......
答案 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}}。