java - DateTimeFormatter.parse(s) 在到达 s 末尾时抛出:为什么?
问题描述
我一直在尝试使用 DateTimeFormatter 来解析“20141112152340”形式的日期/时间字符串。当我调用 formatter.parse(input); 它引发了一个例外:
java.time.format.DateTimeParseException:无法在索引 14 处解析文本“20141112152340”
这是一个最小的完整复制器:
package com.example.minimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
public class Reproducer {
public static void main(String[] args) {
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR) // 4
.appendValue(ChronoField.MONTH_OF_YEAR) // 2
.appendValue(ChronoField.DAY_OF_MONTH) // 2
.appendValue(ChronoField.HOUR_OF_DAY) // 2
.appendValue(ChronoField.MINUTE_OF_HOUR) // 2
.appendValue(ChronoField.SECOND_OF_MINUTE) // 2
.toFormatter()
// Using the default ResolverStyle appears to make no difference.
.withResolverStyle(ResolverStyle.STRICT); // expect 14 characters
String input = "20141112152340";
System.out.printf("length of input is %02d: [%s]; format is %s\n", input.length(), input, formatter.toString());
// When the minute of hour is < 10, it is rendered without zero-padding. Perhaps this
// is related. But, the same problem is reproducible on input strings that do not contain zeroes.
System.out.printf("Current local time in that format is [%s]\n", formatter.format(LocalDateTime.now()));
// The following line throws java.time.format.DateTimeParseException: Text '20140816152340' could not be parsed at index 14
TemporalAccessor parsed = formatter.parse(input);
// NOTREACHED
LocalDateTime stamp = parsed.query(LocalDateTime::from);
System.out.println("Time stamp is " + stamp.toString());
}
}
这是该程序的输出:
length of input is 14: [20141112152340]; format is Value(Year)Value(MonthOfYear)Value(DayOfMonth)Value(HourOfDay)Value(MinuteOfHour)Value(SecondOfMinute)
Current local time in that format is [20191010183335]
Exception in thread "main" java.time.format.DateTimeParseException: Text '20141112152340' could not be parsed at index 14
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1874)
at com.example.minimal.Reproducer.main(Reproducer.java:28)
据我所知,解析器在它到达字符串末尾的那一刻就开始了。由于它正在寻找更多数据而发生这种情况,我尝试将解析器样式从默认切换为严格,但这似乎没有什么区别。
我的问题是,为什么会发生这种情况,以及如何更正我的代码以便它可以解析这个日期/时间表示?
解决方案
以下格式化程序对我有用:
DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
toString()
两种格式化程序都揭示了差异:
Value(Year)Value(MonthOfYear)Value(DayOfMonth)Value(HourOfDay)Value(MinuteOfHour)Value(SecondOfMinute)
对比
Value(YearOfEra,4,19,EXCEEDS_PAD)Value(MonthOfYear,2)Value(DayOfMonth,2)Value(HourOfDay,2)Value(MinuteOfHour,2)Value(SecondOfMinute,2)
如您所见,第二个格式化程序,即工作版本,似乎有明确的字段宽度以及明确的SignStyle
我们可以使用构建器创建相同的格式化程序:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR_OF_ERA, 4, 19, SignStyle.EXCEEDS_PAD)
.appendValue(ChronoField.MONTH_OF_YEAR, 2)
.appendValue(ChronoField.DAY_OF_MONTH, 2)
.appendValue(ChronoField.HOUR_OF_DAY, 2)
.appendValue(ChronoField.MINUTE_OF_HOUR, 2)
.appendValue(ChronoField.SECOND_OF_MINUTE, 2)
.toFormatter()
.withResolverStyle(ResolverStyle.STRICT);
但是,看起来您可以用YEAR_OF_ERA
类似YEAR
的结果替换。
推荐阅读
- pine-script - Pine-Script:使用变量的历史数据时 plot() 不起作用
- sequelize.js - Sequelize 范围内的 BelongsTo / HasMany 无法包含
- django - 生产中的 mod_wsgi 设置无法启动
- html - css父位置随子高度变化而变化
- javascript - 如何删除“输入类型文件文本字段”
- javascript - 如何合并两个没有不在主对象中的键的对象?
- rust - 将元素添加到 Rust 中的可变向量列表
- node.js - Firebase Cloud 功能问题.. 无法读取参数
- swift - 对如何在 APIClient.swift 类中创建 Stripe 临时密钥感到困惑
- pentaho - pentaho 有没有办法在选择值步骤中放置变量?