我希望这两种格式化程序是等价的:
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'
我错过了什么?
答案 0 :(得分:3)
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:
以每周为基础的第一周是标准ISO年度的第一周,在新的一年中至少有4天。
- 如果1月1日 st 是星期一,则第1周从1月1日开始 st
- 如果1月1日 st 是星期二,那么第1周将于12月31日 st 开始上一个标准年度
- 如果1月1日 st 是星期三,则第1周开始于上一标准年12月30日 th
- 如果1月1日 st 是星期四,则第1周开始于上一标准年12月29日 th
- 如果1月1日 st 是星期五,那么第1周将从1月4日开始 th
- 如果1月1日 st 是星期六,那么第1周将从1月3日开始 rd
- 如果1月1日 st 是星期日,那么第1周将于1月2日开始 nd
由于2017-01-01
是星期日,它对应于上一行:第1周从 1月2日 nd 2017 开始,所以 1月1日 st 2017 仍然在2016年的最后一周。
您可以通过调用用于calculate the values of the respecitive week-based fields的方法WeekFields
和IsoFields
来检查getFirstDayOfWeek()
实例与getMinimalDaysInFirstWeek()
的不同之处:
一周定义如下:
- 第一天的一周。例如,ISO-8601标准将星期一视为第一个星期。
- 第一周的最少天数。例如,ISO-8601标准计算第一周需要至少4天。
这两个值可以将一年或一个月分成几周。
在我正在使用的JVM中,默认语言环境为pt_BR
,并且创建的WeekFields
的第一天是星期日,第一周的最小天数为{{1 }}。检查你的,你会发现它也与1
不同。
您可以使用constant WeekFields.ISO
来检查ISO的定义:IsoFields
返回星期一,getFirstDayOfWeek()
返回getMinimalDaysInFirstWeek()
。
另外,请注意4
和IsoFields
之间存在细微差别。引用JodaStephen's comment in this thread:
唯一可观察的差异是WeekFields在所有日历系统上运行(通过转换为ISO),而IsoFields仅在ISO上运行(并拒绝其他日历系统)