基于周的模式不能按预期工作

时间:2017-09-04 11:47:53

标签: java date-formatting java-time week-number

我希望这两种格式化程序是等价的:

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'

我错过了什么?

1 个答案:

答案 0 :(得分:3)

Yw模式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的方法WeekFieldsIsoFields来检查getFirstDayOfWeek()实例与getMinimalDaysInFirstWeek()的不同之处:

  

一周定义如下:

     
      
  • 第一天的一周。例如,ISO-8601标准将星期一视为第一个星期。
  •   
  • 第一周的最少天数。例如,ISO-8601标准计算第一周需要至少4天。
  •   
     

这两个值可以将一年或一个月分成几周。

在我正在使用的JVM中,默认语言环境为pt_BR,并且创建的WeekFields的第一天是星期日,第一周的最小天数为{{1 }}。检查你的,你会发现它也与1不同。

您可以使用constant WeekFields.ISO来检查ISO的定义:IsoFields返回星期一,getFirstDayOfWeek()返回getMinimalDaysInFirstWeek()

另外,请注意4IsoFields之间存在细微差别。引用JodaStephen's comment in this thread

  

唯一可观察的差异是WeekFields在所有日历系统上运行(通过转换为ISO),而IsoFields仅在ISO上运行(并拒绝其他日历系统)

相关问题