Home > Net >  DateTimeFormatter of YYYY-ww resolves differently on mac and ubuntu
DateTimeFormatter of YYYY-ww resolves differently on mac and ubuntu

Time:05-30

System.out.println(
    DateTimeFormatter.ofPattern("YYYY-ww").withZone(ZoneOffset.UTC).format(Instant.parse("2022-05-10T00:00:00.00Z"))
);
System.out.println(
    DateTimeFormatter.ofPattern("YYYY-ww").withZone(ZoneOffset.UTC).format(Instant.parse("2022-05-17T00:00:00.00Z"))
);

Why this pattern YYYY-ww resolves differently on Ubuntu and Mac:

Ubuntu: (default locale en_US, my computer)

2022-20
2022-21

Mac: (default locale en_GB)

2022-19
2022-20

EDIT

System.out.println(
    DateTimeFormatter.ofPattern("YYYY-ww").withLocale(Locale.UK).withZone(ZoneOffset.UTC).format(Instant.parse("2022-05-10T00:00:00.00Z"))
);
System.out.println(
    DateTimeFormatter.ofPattern("YYYY-ww").withLocale(Locale.UK).withZone(ZoneOffset.UTC).format(Instant.parse("2022-05-17T00:00:00.00Z"))
);

returns:

2022-19
2022-20 

Still, the question is why pattern ww is Locale specific? I don't see that in documentation for https://docs.oracle.com/javase/8/docs/api/java/time/temporal/WeekFields.html or https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

CodePudding user response:

In the US locale, the first week of the year can have one to seven days, whereas in the UK, the first week of the year needs to have at least 4 days.

WeekFields.of(Locale.UK).getMinimalDaysInFirstWeek() // 4
WeekFields.of(Locale.US).getMinimalDaysInFirstWeek() // 1

Also, a US week starts on a Sunday, whereas a UK week starts on a Monday.

This means that for the US, the first week of 2022 is the single Saturday of 2022-01-01, and 2022-01-02 is the start of the second week. On the other hand, for the UK, the first week of 2022 starts from 2022-01-03, since the first two days of the year don't form a week. And this is where that extra week for the US machine came about.

When creating a DateTimeFormatter using ofPattern, the default formatting locale of the machine is used:

The formatter will use the default FORMAT locale. This can be changed using withLocale(Locale) on the returned formatter

Hence the difference.

I suppose you want ISO weeks here, and not want anything to do with locales. One way to do this is to construct a DateTimeFormatter using IsoFields:

var dtf = new DateTimeFormatterBuilder()
  .  appendValue(IsoFields.WEEK_BASED_YEAR, 4)
    .appendLiteral('-')
    .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2)
    .toFormatter().withZone(ZoneOffset.UTC);
System.out.println(
    dtf.format(Instant.parse("2022-05-10T00:00:00.00Z"))
);
System.out.println(
    dtf.format(Instant.parse("2022-05-17T00:00:00.00Z"))
);
  • Related