java - 基于周的模式无法按预期工作

标签 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'

我错过了什么?

最佳答案

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 :

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/

相关文章:

java - Java 有没有办法将字符串转换为 MMddyyyy 或 Mddyyyy 日期?

java - 在 java 18 版本中不使用 main 方法时我没有收到任何错误

java - 自动运行外部应用程序,使用 Cucumber 来测试主应用程序

javascript - 格式化日期时间特定时区

asp.net-mvc - 像 .NET 中的 moment.js 一样格式化日期

java - 日期格式和分配

java - 有没有一种简单的方法可以将迭代器复制到 Java 列表中?

Java netty客户端无法向服务器发送消息,但telnet到服务器正常

java-8 - Java8 LocalDateTime到XMLGregorianCalender删除 "+05:30"部分

java - 在 Java 中解析日期时间字符串是否需要 `Locale`?