Setting values of Java Calendar does not give expected date-time

java, java.util.calendar

Solution

You need to set the time zone first. See the definition of GregorianCalendar.setTimeZone below:

public void setTimeZone(TimeZone value)
{
    zone = value;
    sharedZone = false;
    /* Recompute the fields from the time using the new zone.  This also
     * works if isTimeSet is false (after a call to set()).  In that case
     * the time will be computed from the fields using the new zone, then
     * the fields will get recomputed from that.  Consider the sequence of
     * calls: cal.setTimeZone(EST); cal.set(HOUR, 1); cal.setTimeZone(PST).
     * Is cal set to 1 o'clock EST or 1 o'clock PST?  Answer: PST.  More
     * generally, a call to setTimeZone() affects calls to set() BEFORE AND
     * AFTER it up to the next call to complete().
     */
    areAllFieldsSet = areFieldsSet = false;
}

Problem

I have an hour, minute, date and millisecond timestamp, and am trying to create a Date object representing the time. The timestamp is provided in Eastern Daylight Time. In dissecting the problem, I created some simple test code to see what was happening and have observed the following: ``` Date today = new Date(); int hour = 4, min = 0, sec = 0, ms = 64; boolean print = true; Calendar cal = GregorianCalendar.getInstance(); if(print) System.out.println("After initializing, time is: "+cal.getTime()); cal.clear(); if(print) System.out.println("After clearing, time is: "+cal.getTime()); cal.setTime(today); if(print) System.out.println("After setting date, time is: "+cal.getTime()); cal.set(Calendar.HOUR_OF_DAY,hour); if(print) System.out.println("After setting hour, time is: "+cal.getTime()); cal.set(Calendar.MINUTE,min); if(print) System.out.println("After setting minute, time is: "+cal.getTime()); cal.set(Calendar.SECOND,sec); if(print) System.out.println("After setting second, time is: "+cal.getTime()); cal.set(Calendar.MILLISECOND,ms); if(print) System.out.println("After setting milliseconds, time is: "+cal.getTime()); cal.setTimeZone(TimeZone.getTimeZone("EDT")); System.out.println("After setting time zone, time is: "+cal.getTime()); ``` This produces the output: ``` After initializing, time is: Tue Jan 07 16:01:59 EST 2014 After clearing, time is: Thu Jan 01 00:00:00 EST 1970 After setting date, time is: Tue Jan 07 16:01:59 EST 2014 After setting hour, time is: Tue Jan 07 04:01:59 EST 2014 After setting minute, time is: Tue Jan 07 04:00:59 EST 2014 After setting second, time is: Tue Jan 07 04:00:00 EST 2014 After setting milliseconds, time is: Tue Jan 07 04:00:00 EST 2014 After setting time zone, time is: Tue Jan 07 04:00:00 EST 2014 ``` However, if I change the code slightly: ``` boolean print = false; ``` I get the following (different) result (!) ``` After setting time zone, time is: Mon Jan 06 23:00:00 EST 2014 ``` Does anyone know why this is happening?

Original source