3

If you consider that week will start from Jan 01 of every year & week start is SUNDAY then there will be 53 weeks in 2019. Following above Jan 29,30,31 2019 will be into Week-53 of 2019.

As given in documentation of IsoFields for WEEK_OF_WEEK_BASED_YEAR that all three fields are validated against their range of valid values. The week-of-week-based-year field is validated from 1 to 52 or 53 depending on the week-based-year.

So I'm assuming that following code should give the output as: WEEK_OF_WEEK_BASED_YEAR 53 & WEEK_BASED_YEAR 2019.

But it's giving output as: 1 & 2020

import java.time.LocalDate;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
import java.time.temporal.IsoFields;

public class WeekStartDemo {
    public static void main(String args[]) {
        DateTimeFormatter DATE_FORMATTER = DateTimeFormatter
                .ofPattern("uuuu-MM-dd")
                .withChronology(IsoChronology.INSTANCE)
                .withResolverStyle(ResolverStyle.STRICT);

        LocalDate updatedDate = LocalDate.parse("2019-12-30", DATE_FORMATTER);

        System.out.println(updatedDate.toString());

        System.out.println(updatedDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
        System.out.println(updatedDate.get(IsoFields.WEEK_BASED_YEAR));
    }
}

If I pass the date as 2019-12-28 then it's returning WEEK_OF_WEEK_BASED_YEAR 52 & WEEK_BASED_YEAR 2019. But doesn't work for last week of 2019 (which is 53rd week)

Let me know what I'm missing in above code.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
AshwinK
  • 1,039
  • 1
  • 12
  • 31
  • 1
    *The week-based-year itself is defined relative to the standard ISO proleptic year. It differs from the standard year in that it always starts on a **Monday**.* – Elliott Frisch Jan 08 '20 at 05:48

4 Answers4

2

As I mentioned in the comments, and from your Javadoc link for IsoFields, The week-based-year itself is defined relative to the standard ISO proleptic year. It differs from the standard year in that it always starts on a Monday (not a Sunday). It should be easy enough to find the years with 53 weeks using your posted code, iterate from 1900 to 2300 and parse the WEEK_OF_WEEK_BASED_YEAR for the last day of the given year and print the values where it is 53. Like,

DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("uuuu-MM-dd")
        .withChronology(IsoChronology.INSTANCE)
        .withResolverStyle(ResolverStyle.STRICT);

for (int i = 1900; i < 2300; i++) {
    LocalDate updatedDate = LocalDate.parse(String.format("%d-12-31", i), DATE_FORMATTER);
    if (updatedDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) == 53) {
        System.out.println(i);
    }
}

The first few values I get are

1903
1908
1914
1920
1925
1931
1936
1942

skipping ahead a bit...

2009
2015
2020
2026

So this year (2020) has 53 weeks, and 2019 does not.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • If you use `ISO proleptic year` in that case 2019 has 52 week which is correct. Yes, it was my bad that I missed JavaDoc of `ISOFields` given. But if you consider `WeekStart: SUNDAY` & from every `Jan 01` new week (which is Week-01) starts in that case 2019 will have 53 weeks. Last Week-53 will have `3 days: 29,30,31. That's what I've posted in my OP. – AshwinK Jan 08 '20 at 07:52
1
    LocalDate date = LocalDate.of(2019, Month.DECEMBER, 30);
    int weekOfYear = date.get(WeekFields.SUNDAY_START.weekOfYear());
    System.out.println(weekOfYear);

Output from this snippet is:

53

I believe that this is the exact difference between WeekFields.weekOfWeekBasedYear() and WeekFields.weekOfYear().

It may also be that your main source of confusion is using the wrong week fields, as Elliott Frisch also mentioned. The ISO week fields that you use define Monday as the first day of the week and week one of the year as the first week containing at least 4 days of the year. In contrast you said that you wanted:

If you consider that week will start from Jan 01 of every year & week start is SUNDAY

From your comments:

… will the new week (Week-01) will always start on Jan 01 of every year ?

Yes it will.

How can I perform minus 1 week on this weekOfYear ? As for Jan 01,2020, weekOfYear will be Week-01 2020. What type of minus 1 week I can perform to get weekOfYear as Week-53 2019 ? I tried with date.minusWeeks(1) but it returns Week-52 2019

    LocalDate dateInWeek1 = LocalDate.of(2020, Month.JANUARY, 3);
    int weekOfYear = dateInWeek1.get(wf.weekOfYear());
    System.out.println(weekOfYear);
    LocalDate dateInPreviousWeek;
    if (weekOfYear == 1) {
        dateInPreviousWeek = dateInWeek1.minusWeeks(1)
                .with(TemporalAdjusters.lastDayOfMonth());
    }
    else {
        dateInPreviousWeek = dateInWeek1.minusWeeks(1);
    }
    System.out.format("%s %2d%n", dateInPreviousWeek, dateInPreviousWeek.get(wf.weekOfYear()));

We need to handle the case of week 1 specially. When subtracting 1 week, we know we are getting into December the previous year. Selecting the last day of the month will give us December 31. This will always be in the last week of the year (usually week 53; occasionally week 54 if in a leap year that begins on a Saturday, I think that years 2000 and 2028 are examples of this).

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • I agree with you and @Elliott Frisch that I contrasted two things. But If I use what you've provided in that case will the new week (`Week-01`) will always start on `Jan 01` of every year ? Nevertheless it has 1/2/3/4 days in week. As in current year(2020) `Week-01` will be from `Jan 01, 2020` to `Jan 04,2020` & `Week-02` will be from `Jan 05,2020` to `Jan 11,2020`. – AshwinK Jan 08 '20 at 07:57
  • I've subsequent question on the same. How can I perform minus 1 week on this `weekOfYear` ? As for `Jan 01,2020`,`weekOfYear` will be `Week-01 2020`. What type of `minus 1 week` I can perform to get `weekOfYear` as `Week-53 2019` ? I tried with `date.minusWeeks(1)` but it returns `Week-52 2019` – AshwinK Jan 08 '20 at 08:21
  • 1
    Interesting supplementary questions @AshwinK. Please see my quick edit. I am sorry that I don’t have time to go into more depth right now. I hope you will be able to explore further on your own. – Ole V.V. Jan 08 '20 at 20:09
  • Thanks I explored & I'll edit original question as well for the approach I've used. – AshwinK Jan 09 '20 at 05:03
0

The issue here is that a given year has either 365 or 366 days (the latter for a leap year), which means that every year has either 1 or 2 days extra beyond 52 weeks. The ISO system for week years is what handles this, and it means that sometimes the first week of the year might not start of the 1st of January, nor would the last day of a year fall in the 52nd week. One workaround here would be to just calculate the week starting from the beginning of each year, e.g.

LocalDate firstOfYear = LocalDate.of(2019, Month.JANUARY, 1);
LocalDate updatedDate = LocalDate.of(2019, Month.DECEMBER, 30);

int diff = (int)ChronoUnit.DAYS.between(firstOfYear, updatedDate);
int week = 1 + (diff / 7);
System.out.println("The week number is: " + week);
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • Should such hand-held conversion be necessary? Asking because I’d be surprised if it was. – Ole V.V. Jan 08 '20 at 05:56
  • @Ole I would also be surprised, but I don't know the Java 8 date API that well. I think my answer is in the right direction at least, namely the OP either wants to count year-weeks, or defines a week as starting on 1st January. – Tim Biegeleisen Jan 08 '20 at 05:59
  • This solution is straight forward I know. But I'm more looking into Java's internal API which should provide week. Because you can't set week starting/week minimum days, etc kind of things in it. – AshwinK Jan 08 '20 at 07:43
0

Based on the ISO-8601 (https://www.cl.cam.ac.uk/~mgk25/iso-time.html) this is correct. 2019 has no calendarweek 53. Week 01 of a year is per definition the first week that has the Thursday in this year, which is equivalent to the week that contains the fourth day of January. As far as I know this is done to avoid a cw 1 without a workday.

TobiSH
  • 2,833
  • 3
  • 23
  • 33
  • That is correct, I missed the documentation `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.` But what APIs of Java I can use to meet my requirement where Week will always start from Jan 01 & it will end first upcoming `SATURDAY` (as new week start is `SUNDAY`) – AshwinK Jan 08 '20 at 07:48