0

I want to get this current week on the day of 9/10/2018 as the 42 week of the year after setting the First Day of the week to Sunday. Still I get the output as 41 from the below snippet

 Calendar c = Calendar.getInstance();
 c.setFirstDayOfWeek(Calendar.SUNDAY);
 System.out.println( c.get(Calendar.WEEK_OF_YEAR)  );

Am I missing something here?

Background: Our week start can be variable. Our configuration has the ability to let users decide the first day of the week.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
vkandvia
  • 85
  • 12
  • 1
    What makes you expect 42??!! Tuesday, January 2 was just 40 weeks ago. Should the week from December 24 through 30 last year have been week 1 of this year?? – Ole V.V. Oct 09 '18 at 06:50
  • 1
    The `Calendar` class is long outdated and frankly somewhat complicated to work with. I recommend [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/) instead. I don’t say the following is straightforward, but I find it clearer and less error-prone: `LocalDate.now(yourTimeZone).get(WeekFields.SUNDAY_START.weekOfWeekBasedYear())`. Today, 2018-10-09, it gives 41, though, which is what I think is correct and agrees with [Week Numbers 2018 in United States](https://savvytime.com/week-number/united-states/2018). – Ole V.V. Oct 09 '18 at 06:55
  • But what if my week start can be variable? someone may keep it as Monday even then how should I go about it? #verynewtojava – vkandvia Oct 09 '18 at 07:13
  • Week numbering requires more than knowing the first day of the week. In ISO the first week of the year is the week that has at least four days in the new yer, in the USA only one day is required. Also, seriously, I doubt that any user wants to use a homegrown numbering scheme that no one else is using. Do you expect they will? – Ole V.V. Oct 09 '18 at 07:16
  • They will rarely use it.. but our configuration hes the ability to let them do that.. anyway looks like I will try to do a bit of modulo arithmetic based on the first day of the year and the number day of the year to figure this out – vkandvia Oct 09 '18 at 07:24
  • Please think twice, no, three times before making your own calculation. Such are easy to get wrong, and your code will be hard to read and maintain. You can make your custom `WeekFIelds` object to suit your needs (as long as you don’t require the week year to start on December 24). Understand how it works, use it. If it really turns out your users require something it doesn’t give you (which I much doubt), it’s probably better to subtract 1 from the week number it gives you than to roll your complete own calculation. – Ole V.V. Oct 10 '18 at 01:46
  • Yes.. I am using some of the API for this calculation.. using the Temporal adjusters I am getting the date on the last day of the week. After that dividing the Day of the Year from the API by 7 does seem to work for me. – vkandvia Oct 10 '18 at 02:06
  • It had been suggested that this question was a duplicate of [java Calendar setFirstDayOfWeek not working](https://stackoverflow.com/questions/29227153/java-calendar-setfirstdayofweek-not-working), which I consider incorrect, but still giving the link here for the sake of completeness. – Ole V.V. Oct 10 '18 at 02:39
  • Week of Year is different than Week -- Week of year means you will get 53 weeks in a year sometimes. – trilogy Oct 10 '18 at 03:40
  • Thanks Ole.V.V. I did go through the link earlier.. My requirement was such that someone could set the start of week to Thursday even and then the week of year could change.. anyway I have been able to get things working thanks to the pointers here.. – vkandvia Oct 10 '18 at 04:04

1 Answers1

2

Sorry if I’m too persistent. I still think you should leave the calculation to a custom WeekFields object. If I understood your comment correctly, you want:

    final int daysPerWeek = DayOfWeek.values().length; // A wordy way of writing 7 :-)
    WeekFields customWeekFields = WeekFields.of(firstDayOfWeek, daysPerWeek);
    int customWeekNumber = date.get(customWeekFields.weekOfWeekBasedYear());

To test whether this agrees with what you are already doing I wrote the following method:

static void printWeekNumber(DayOfWeek firstDayOfWeek, LocalDate date) {
    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("EEE uuuu-MM-dd", Locale.ENGLISH);
    final int daysPerWeek = DayOfWeek.values().length;

    // Week number according to your comment: “using the Temporal adjusters
    // I am getting the date on the last day of the week.
    // After that dividing the Day of the Year from the API by 7”
    DayOfWeek lastDayOfWeek = firstDayOfWeek.minus(1);
    int askersCommentWeekNumber = date
            .with(TemporalAdjusters.nextOrSame(lastDayOfWeek))
            .getDayOfYear()
                    / daysPerWeek;

    // My suggested way of calculating the same week number
    WeekFields customWeekFields = WeekFields.of(firstDayOfWeek, daysPerWeek);
    int customWeekNumber = date.get(customWeekFields.weekOfWeekBasedYear());

    System.out.format(Locale.ENGLISH, "Week begins on %-8s Date is %s. Week %2d or %2d, agree? %s%n", 
            firstDayOfWeek, date.format(dateFormatter), 
            askersCommentWeekNumber, customWeekNumber, 
            askersCommentWeekNumber == customWeekNumber);
}

To make it easier to check the calculations by hand, I have picked a date in January in different years:

    printWeekNumber(DayOfWeek.SUNDAY, LocalDate.of(2017, Month.JANUARY, 9));
    printWeekNumber(DayOfWeek.MONDAY, LocalDate.of(2017, Month.JANUARY, 9));
    printWeekNumber(DayOfWeek.THURSDAY, LocalDate.of(2017, Month.JANUARY, 9));
    printWeekNumber(DayOfWeek.SUNDAY, LocalDate.of(2018, Month.JANUARY, 9));
    printWeekNumber(DayOfWeek.MONDAY, LocalDate.of(2018, Month.JANUARY, 9));
    printWeekNumber(DayOfWeek.SUNDAY, LocalDate.of(2019, Month.JANUARY, 9));
    printWeekNumber(DayOfWeek.MONDAY, LocalDate.of(2019, Month.JANUARY, 9));

Output:

Week begins on SUNDAY   Date is Mon 2017-01-09. Week  2 or  2, agree? true
Week begins on MONDAY   Date is Mon 2017-01-09. Week  2 or  2, agree? true
Week begins on THURSDAY Date is Mon 2017-01-09. Week  1 or  1, agree? true
Week begins on SUNDAY   Date is Tue 2018-01-09. Week  1 or  1, agree? true
Week begins on MONDAY   Date is Tue 2018-01-09. Week  2 or  2, agree? true
Week begins on SUNDAY   Date is Wed 2019-01-09. Week  1 or  1, agree? true
Week begins on MONDAY   Date is Wed 2019-01-09. Week  1 or  1, agree? true

Please check whether the results are as you want them, though. For the example in your question, the result is neither 41 nor 42:

    printWeekNumber(DayOfWeek.SUNDAY, LocalDate.of(2018, Month.OCTOBER, 9));
Week begins on SUNDAY   Date is Tue 2018-10-09. Week 40 or 40, agree? true

Edit: If you want ISO 8601 week numbers, use date.get(WeekFields.ISO.dayOfWeek()). If you want your custom first day of week and 4 days in the first week as in ISO 8601, use:

    WeekFields customWeekFields = WeekFields.of(firstDayOfWeek, 4);
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    You were correct! My calculation was not right... Thanks a lot for being so persistent and helpful! Your solution does work! Oddly though 1 Jan 2017 is the 52nd week, still my QA is okay with the outcome. – vkandvia Oct 11 '18 at 00:39
  • 1 Jan 2017 was a Sunday. So if your week begins in Monday (or for example Thursday), then week 1 has not yet begun on 1 Jan, so it belings to the last week of 2016, that is, week 52. If the week begins on Sunday, then 1 Jan 2017 should belong to week 1 (I haven’t tested this particular case). – Ole V.V. Oct 11 '18 at 04:33
  • It doesnt belong to week 1.. Seems like an international standard https://www.epochconverter.com/weeks/2017. – vkandvia Oct 12 '18 at 12:50
  • Thank you, @vkandvia, for suggesting an edit. I believe it wasn’t correct, so instead I have added a little information at the bottom of the answer. – Ole V.V. Jan 08 '19 at 07:55