Search code examples
javacalendargregorian-calendar

GregorianCalendar: Jumping from tuesday to sunday


I have a GregorianCalendar instance for Tuesday September 2nd. The valñue is checked in milliseconds and is OK. I want another calendar which is the next Sunday (7th) at 23:59:59. So:

GregorianCalendar currentCalendar = MyClock.INSTANCE.getCurrentCalendar();
GregorianCalendar nextSunday =
    (GregorianCalendar)currentCalendar.clone();
// GregorianCalendar uses Sunday as first day of week, so we must
// advance one week
int currentWeek = nextSunday.get(GregorianCalendar.WEEK_OF_YEAR);
nextSunday.set(GregorianCalendar.WEEK_OF_YEAR,
    currentWeek + this.THIS_WEEK);
nextSunday.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.SUNDAY);
nextSunday.set(GregorianCalendar.HOUR_OF_DAY, 23);
nextSunday.set(GregorianCalendar.MINUTE, 59);
nextSunday.set(GregorianCalendar.SECOND, 59);
nextSunday.set(GregorianCalendar.MILLISECOND, 0);

So, since sunday is day number 1 of the week for the GregorianCalendar, and I am at week of year number 36, I add one week and then set the day to sunday.

The real problems comes now: when I execute in my development machine, with OpenJDK 1.7.0_55, it works perfectly. If I go to my test machine with OpenJDK 1.7.0_51, it does it all wrong:

Adds one week until tuesday 9th, and then goes to sunday 14th instead of sunday 7th.

I don't know if I am doing it right or wrong: what is really killing me is that the result depends on the machine, and I haven't found any difference at GregorianCalendar at those OpenJDK versions. Any explanation for this behaviour?

PD: Please stick to GregorianCalendar. I know is a bit shitty, but I don't want to use Joda Calendar or any other at current stage of development.

EDIT: I found method setWeekDate(year, week_of_year, day_of_week). One would think that setting year, week and day of week into the same method will grant it will succeed. It does not: still going from 2nd to 14th. What monkey wrote this?


Solution

  • I've made slight alterations to your code:

    SimpleDateFormat sdf = new SimpleDateFormat("dd MM yyyy - HH:mm:ss.SSSS Z");
    GregorianCalendar currentCalendar = (GregorianCalendar) Calendar.getInstance();
    currentCalendar.set(Calendar.DAY_OF_MONTH, 2);
    System.out.println(sdf.format(currentCalendar.getTime()));
    GregorianCalendar nextSunday = (GregorianCalendar) currentCalendar.clone();
    // GregorianCalendar uses Sunday as first day of week, so we must
    // advance one week
    int currentWeek = nextSunday.get(GregorianCalendar.WEEK_OF_YEAR);
    nextSunday.set(GregorianCalendar.WEEK_OF_YEAR, currentWeek + 1);
    nextSunday.set(GregorianCalendar.DAY_OF_WEEK, GregorianCalendar.SUNDAY);
    nextSunday.set(GregorianCalendar.HOUR_OF_DAY, 23);
    nextSunday.set(GregorianCalendar.MINUTE, 59);
    nextSunday.set(GregorianCalendar.SECOND, 59);
    nextSunday.set(GregorianCalendar.MILLISECOND, 0);
    System.out.println(sdf.format(nextSunday.getTime()));
    

    This outputs:

    02 12 2014 - 19:40:46.0250 +0200
    07 12 2014 - 23:59:59.0000 +0200
    

    Which is correct. However, I have two things to point out:

    1. check the value of this.THIS_WEEK. I have substituted it for the value 1 and it works ok on my machine.
    2. check the timezone on both machines (in my case GMT+2). Since both machines use the same code which both initialize the values and use them, there shouldn't really be problems. But if you use the values as milliseconds on a different machine (e.g. exposing the value through a webservice or something), you might hit problems.