DateTimeFormatter 可以解析,但不能为相同的输入格式化

DateTimeFormatter can parse, but not format for same input

模式 "yyyy_'w'w"DateTimeFormatter 无法格式化已解析的值。

val df = DateTimeFormatter.ofPattern("yyyy_'w'w")
df: DateTimeFormatter = Value(YearOfEra,4,19,EXCEEDS_PAD)'_''w'Localized(WeekOfWeekBasedYear,1)

val week = df.parse("2017_w19")
week: temporal.TemporalAccessor = {Year=2017, WeekOfWeekBasedYear[WeekFields[SUNDAY,1]]=19},ISO

df.format(week)

错误是:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra
  java.time.format.Parsed.getLong(Parsed.java:203)
  java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
  java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2540)
  java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2179)
  java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1746)
  java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1720)

这是为什么?

对我来说,您不能使用 DateTimeFormatter 来格式化 TemporalAccessor,它对于时间来说是一个过于宽泛的接口。首先尝试将其转换为 DateTime 对象。

模式 yyyy 代表 year-of-era field. But according to javadoc, there's also the pattern uuuu to represent the year field(阅读这些链接以了解它们之间的细微差别 - 尽管对于当前日期而言差别不大)。

问题是:当您使用 y 创建格式化程序时,它使用 时代 字段,正如您可以通过值看到的那样:

Value(YearOfEra,4,19,EXCEEDS_PAD)

但是在解析时,生成的解析对象(在您的例子中是 week 变量)是使用 year 字段创建的 - 正如您可以通过值看到的:

{Year=2017, ...


格式化程序使用 年代 字段设置。因此,当您尝试格式化 week 时,它会尝试从 week 变量中获取此字段。由于此字段不存在(week 仅包含 year,但不包含 year-of-era),它抛出 UnsupportedTemporalTypeException.

解决方案是在格式化程序中使用 year 字段(u 模式):

val df = DateTimeFormatter.ofPattern("uuuu_'w'w")
println(df)
val week = df.parse("2017_w19")
println(week)
println(df.format(week))

输出将是:

Value(Year,4,19,EXCEEDS_PAD)'_''w'Localized(WeekOfWeekBasedYear,1)
{Year=2017, WeekOfWeekBasedYear[WeekFields[SUNDAY,1]]=19},ISO
2017_w19

请注意,现在格式化程序是使用 year 字段创建的,并且 format 方法现在尝试从解析的对象中获取此字段,并且没有例外抛出。