@Kayaman 接受的答案不正确,因为您不能混合标准日期表示(使用 yyyy = 年份)和周日期表示(使用 ww = 基于周的年份)。标准日历年和基于周的年之间的细微差别在日历年的开始或结束时是相关的。结论:不要使用符号“y”,而应使用符号“Y”。输入“201501”的反例:
正确的解决方案
DateTimeFormatter formatter =
new DateTimeFormatterBuilder()
.appendValue(WeekFields.ISO.weekBasedYear(), 4)
.appendValue(WeekFields.ISO.weekOfWeekBasedYear(), 2)
.parseDefaulting(ChronoField.DAY_OF_WEEK, 1)
.toFormatter();
LocalDate startDate = LocalDate.parse("201501", formatter);
System.out.println(startDate); // 2014-12-29
基于@Kayaman 的提议:
DateTimeFormatter dtf =
new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.appendValue(ChronoField.ALIGNED_WEEK_OF_YEAR, 2)
.parseDefaulting(WeekFields.ISO.dayOfWeek(), 1)
.toFormatter();
System.out.println(LocalDate.parse("201501", dtf)); // 2015-01-05 (wrong)
结果日期不同!差异是由日历年的定义引起的,日历年总是从一月一日开始,而基于周的年总是从星期一开始(ISO-8601 定义),使用日历年的第一周,至少有 4 天。
附加说明 a): Java-8 不管理可本地化字段的相邻数字解析,例如基于周的字段(另请参阅相关的JDK 问题),因此我选择了基于构建器的解决方案,而不是定义模式“YYYYww”(然而,Java-9 承诺提供一个解决方案)。但即使使用 Java-9,仍然需要基于构建的方法,因为需要为缺少的星期几定义默认值(此处:设置为星期一)。
附加说明 b):如果您正在寻找基于周的年份和年份的组合的真正类型,并且LocalDate
仅用作这种缺失类型的解决方法,那么您可以在 3rd-party 中找到这样的类型库,在 Threeten-Extra 或我的库Time4J中。例子:
ChronoFormatter<CalendarWeek> cf =
ChronoFormatter.ofPattern(
"YYYYww",
PatternType.CLDR,
Locale.ROOT,
CalendarWeek.chronology()
);
CalendarWeek cw = cf.parse("201501");
System.out.println(cw); // 2015-W01
System.out.println(cw.at(Weekday.MONDAY)); // 2014-12-29