Mongodb $week and Java Calendar.WEEK_OF_YEAR

Mongodb's $week operator states

Takes a date and returns the week of the year as a number between 0 and 53.

Weeks begin on Sundays, and week 1 begins with the first Sunday of the year. Days 
preceding the first Sunday of the year are in week 0. This behavior is the same as the
 ā€œ%Uā€ operator to the strftime standard library function.

whereas, Java Calendar's DAY_OF_WEEK returns slightly differently (US Locale). For instance, for 2013, mongo's week 1 is actually week 2.

My question is, adding arbitrary 1 does not solve the problem. Is there a formula I can use to determine which week number to use to get the week start date.

Scenario: I am running an aggregation in mongo which returns me a week number. Based on the week number, I need to arrive at week start date.

Would something like the following work always? Assume calendar is another instance of Calendar.

    Calendar firstDay = Calendar.getInstance(Locale.US);
    firstDay.set(Calendar.DAY_OF_YEAR, 1);
    int day = firstDay.get(Calendar.DAY_OF_WEEK);
    if (day != Calendar.SUNDAY){
        //both mongo and java calendar start in different weeks so add 1 to reconcile
        calendar.set(Calendar.WEEK_OF_YEAR, number.intValue()+1);
    }
Jon Skeet
people
quotationmark

I would avoid bringing the Java week-of-year into the picture at all - unless you can persuade MongoDB to stop being so broken, somehow. (That's a really odd definition of week-of-year; I'd normally use the ISO-8601 definition.)

If you really need to this with java.util.Calendar, you could probably use something like this (untested):

// You really want to do all of this on a "date" basis, without DST messing
// things up...
Calendar firstDay = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US);
firstDay.set(Calendar.DAY_OF_YEAR, 1);
while (firstDay.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
    firstDay.add(Calendar.DAY, 1);
}

// firstDay is now at the start of week 1 from a mongodb perspective...
// We just need to add the number of weeks.
firstDay.add(Calendar.Day, (mongoWeekNumber - 1) * 7);

Note that if the week number is 0, the start of the week could easily be in a calendar year before the current one.

If you have any choice in which date/time API you use, I would strongly recommend that you use Joda Time or java.time instead of Calendar though - then you can work with LocalDate instead, and have a much saner time.

people

See more on this question at Stackoverflow