Reputation: 1088
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.
Upvotes: 3
Views: 1626
Reputation: 86276
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 isSUNDAY
…
From your comments:
… will the new week (
Week-01
) will always start onJan 01
of every year ?
Yes it will.
How can I perform minus 1 week on this
weekOfYear
? As forJan 01,2020
,weekOfYear
will beWeek-01 2020
. What type ofminus 1 week
I can perform to getweekOfYear
asWeek-53 2019
? I tried withdate.minusWeeks(1)
but it returnsWeek-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).
Upvotes: 1
Reputation: 201447
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.
Upvotes: 2
Reputation: 2921
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.
Upvotes: 0
Reputation: 521249
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);
Upvotes: 0