将字符串解析为本地日期不会使用所需的世纪

Hap*_*ppy 13 java date 2-digit-year java-time

我正在使用这个DateTimeFormatter:

DateTimeFormatter.ofPattern("ddMMYY")
Run Code Online (Sandbox Code Playgroud)

我想解析字符串150790,我得到了这个错误:

Unable to obtain LocalDate from TemporalAccessor: {DayOfMonth=15, MonthOfYear=7, WeekBasedYear[WeekFields[MONDAY,4]]=2090},ISO of type java.time.format.Parsed
Run Code Online (Sandbox Code Playgroud)

显然,我希望得到以下内容TemporalAccessor:

{DayOfMonth=15, MonthOfYear=7, WeekBasedYear=1990}
Run Code Online (Sandbox Code Playgroud)

你知道我为什么得到2090而不是1990年?

谢谢你的帮助

Men*_*ild 16

由于这个问题实际上是关于新java.time包装的,SimpleDateFormat所以我不会引用相关部分:

年份:字母数决定了使用填充的最小字段宽度.如果字母数是2,则使用减少的两位数形式.对于打印,这将输出最右边的两位数字.对于解析,这将使用2000的基值进行解析,从而产生2000到2099(包括2000和2099)范围内的一年.

我们看到Java-8使用的范围是每个默认2000-2099,而不是相当于SimpleDateFormat今天+80年的范围-80岁.

如果要配置它,则必须使用appendValueReduced().这是一个不方便的设计,但可能,请看这里:

String s = "150790";

// old code with base range 2000-2099
DateTimeFormatter dtf1 = 
  new DateTimeFormatterBuilder().appendPattern("ddMMyy").toFormatter();
System.out.println(dtf1.parse(s)); // 2090-07-15

// improved code with base range 1935-2034
DateTimeFormatter dtf2 = 
  new DateTimeFormatterBuilder().appendPattern("ddMM")
  .appendValueReduced(
    ChronoField.YEAR, 2, 2, Year.now().getValue() - 80
  ).toFormatter();
System.out.println(dtf2.parse(s)); // 1990-07-15
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果你真的想要以周为基础的年份,那么你必须使用Y代替y或相应的字段IsoFields.WEEK_BASED_YEAR.关于您没有任何其他与周相关的字段的事实,我会假设正常的日历年,而不是基于周的日历年.