java - 当所有字段(包括分隔符,但不包括年份)都是可选的时,在 Java8 中解析 ISO 8601 日期
问题描述
我需要在 Java 中以不同的精度解析 ISO8601 格式的字符串。我需要解析的字符串的一些示例是:
- 2018
- 2018-10
- 2018-10-15
- 2018-10-15T12:00
- 2018-10-15T12:00:30
- 2018-10-15T12:00:30.123
- 20181015
- 201810151200
- 20181015120030
- 20181015120030.123
- 20181015T12:00:30.123
如果我没有字段,那么我可以自由假设适用的最低有效值(例如,如果缺少月份,我可以假设 1 月,如果缺少日期,则假设当月的第一天,如果时间失踪假设午夜)
我搜索了 SO,我发现的所有示例都假设我事先知道确切的格式。
解决方案
好吧,我花了比我预期的更长的时间。唯一有效的解析器是:
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendPattern("[['-']MM[['-']dd[['T']HH[[':']mm[[':']ss['.'SSS]]]]]]")
.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
.toFormatter();
String[] s = {
"2018",
"2018-10",
"2018-10-15",
"2018-10-15T12:00",
"2018-10-15T12:00:30",
"2018-10-15T12:00:30.123",
"20181015",
"201810151200",
"20181015120030",
"20181015120030.123",
"20181015T12:00:30.123"
};
for (String line : s) {
System.out.println(LocalDateTime.parse(line, dtf));
}
问题是yyyy
创建了一个ValueParser(minWidth=4, maxWidth=19, SignStyle.PAD_EXEEDS)
解析日期20181015
的year=20181015
例子。所以我们必须将数字宽度限制year
为 4。
该文档指出:
Year:字母数决定了使用填充的最小字段宽度。
但没有指定最大宽度。
推荐阅读
- c++ - 我正在尝试使用 -fsanitizer=address 进行编译,但不断收到“找不到 -lasan”
- java - Java 泛型参数是如何推断的?
- ios - UIImagePickerController 只能在主线程中使用 | 应用程序崩溃
- f# - 如何在 F# 中将 Excel 工作表放入 Deedle 数据框
- memory-management - Solaris 中的物理内存利用率
- python - 读取 5gb 以上的 csv 数据集
- gitlab - 阶段对于其他分支是可选的,但对于主分支是强制性的
- linux - __init 函数中的本地静态标识符会发生什么?
- repast-simphony - 批量运行后的模拟可视化
- d3.js - dc.js 中带有 JSON 对象的折线图