基于周的模式无法按预期工作
Week-based pattern does not work as expected
我希望这两个格式化程序是等价的:
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
那样工作。根据 JVM 的默认语言环境,上面创建的 WeekFields
会有不同的行为。
另一方面,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周开始于1月2日nd 2017, 所以1月1日st 2017还在2016年的最后一周
您可以通过调用方法 getFirstDayOfWeek()
和 getMinimalDaysInFirstWeek()
来检查您的 WeekFields
实例与 IsoFields
有何不同 - 它们用于 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()
returns 星期一和 getMinimalDaysInFirstWeek()
returns 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)
我希望这两个格式化程序是等价的:
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
那样工作。根据 JVM 的默认语言环境,上面创建的 WeekFields
会有不同的行为。
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周开始于1月2日nd 2017, 所以1月1日st 2017还在2016年的最后一周
您可以通过调用方法 getFirstDayOfWeek()
和 getMinimalDaysInFirstWeek()
来检查您的 WeekFields
实例与 IsoFields
有何不同 - 它们用于 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()
returns 星期一和 getMinimalDaysInFirstWeek()
returns 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)