我希望这两个格式化程序是等效的:
DateTimeFormatter fromBuilder = new DateTimeFormatterBuilder()
.appendValue(IsoFields.WEEK_BASED_YEAR, 4)
.appendLiteral('-')
.appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2)
.toFormatter();
DateTimeFormatter fromPattern = DateTimeFormatter.ofPattern("YYYY-ww");
但是他们没有给出相同的结果:
LocalDate date = LocalDate.of(2017, 1, 1);
System.out.printf("from builder: %s%n", fromBuilder.format(date)); // prints 'from builder: 2016-52'
System.out.printf("from pattern: %s%n", fromPattern.format(date)); // prints 'from pattern: 2017-01'
我错过了什么?
最佳答案
Y
和w
模式correspond to a localized version of week-fields ,使用 JVM 的默认区域设置 ( java.util.Locale
)。第二个格式化程序相当于:
// localized week fields (using default Locale)
WeekFields weekFields = WeekFields.of(Locale.getDefault());
// equivalent to YYYY-ww
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.appendValue(weekFields.weekBasedYear(), 4)
.appendLiteral('-')
.appendValue(weekFields.weekOfWeekBasedYear(), 2)
.toFormatter();
由于这取决于区域设置,因此它可以或不能像 IsoFields
那样工作。 。 WeekFields
根据 JVM 的默认区域设置,上面创建的将具有不同的行为。
IsoFields
另一方面,遵循 ISO-8601 定义来定义基于周的字段,如 described in the javadoc :
The first week of a week-based-year is the first Monday-based week of the standard ISO year that has at least 4 days in the new year.
- If January 1st is Monday then week 1 starts on January 1st
- If January 1st is Tuesday then week 1 starts on December 31st of the previous standard year
- If January 1st is Wednesday then week 1 starts on December 30th of the previous standard year
- If January 1st is Thursday then week 1 starts on December 29th of the previous standard year
- If January 1st is Friday then week 1 starts on January 4th
- If January 1st is Saturday then week 1 starts on January 3rd
- If January 1st is Sunday then week 1 starts on January 2nd
如2017-01-01
是星期日,它对应于上面的最后一行:第 1 周从 2017 年 1 月 2 日开始,因此 2017 年 1 月 1 日 现在还是2016年的最后一周。
您可以查看您的WeekFields
实例不同于 IsoFields
通过调用方法 getFirstDayOfWeek()
和getMinimalDaysInFirstWeek()
- 习惯 calculate the values of the respecitive week-based fields :
A week is defined by:
- The first day-of-week. For example, the ISO-8601 standard considers Monday to be the first day-of-week.
- The minimal number of days in the first week. For example, the ISO-8601 standard counts the first week as needing at least 4 days.
Together these two values allow a year or month to be divided into weeks.
在我使用的 JVM 中,默认区域设置是 pt_BR
,以及WeekFields
创建的一周的第一天为星期日,第一周的最少天数为 1
。检查你的,你会发现它也不同于 IsoFields
.
您可以使用 constant WeekFields.ISO
检查 ISO 的定义。 :getFirstDayOfWeek()
周一返回,getMinimalDaysInFirstWeek()
返回4
.
另外,请注意 IsoFields
之间存在细微差别。和WeekFields.ISO
。引用JodaStephen's comment in this thread :
The only observable difference was that WeekFields operates on all calendar systems (by converting to ISO) whereas IsoFields only operates on ISO (and rejects other calendar systems)
关于java - 基于周的模式无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46036383/