Q:

Getting a Date from a GregorianCalendar

The GregorianCalendar is being inconsistent:
Calendar cal = new GregorianCalendar(2000, 0, 1);
long testCalOne = cal.getTimeInMillis();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
long testCalTwo = cal.getTimeInMillis();

Calendar cal2 = new GregorianCalendar(2000, 0, 1);
cal2.setTimeZone(TimeZone.getTimeZone("UTC"));
long testCalThree = cal2.getTimeInMillis();

System.out.println(testCalOne + ", " + testCalTwo + ", " + testCalThree);

Results in
946681200000, 946681200000, 946684800000

This represents 2000-01-01 midnight in GMT+1, GMT+1 and UTC respectively. My timezone is +1 hour relative to UTC.
The problem here is that the getTimeInMillis is supposed to return the amount of milliseconds since 1970-01-01 in UTC. Only testCalThree is correct.
Another problem is that setTimeZone is seemingly not working depending on whether I called getTimeInMillis before.
My goal is to take a Calendar I receive as parameter from other code and get a UTC (java.util) Date for further use.

A:

I think it's a bug in the Calendar implementation. time is cached, i.e. if you've calculated it once it is reused unless something changes.
But somehow setting time zone is not recognized as a relevant change.
You can force re-calculation of time in ms by changing or clearing some field explicitly. So this:
    Calendar cal = new GregorianCalendar(2000, 0, 1);
    long testCalOne = cal.getTimeInMillis();
    cal.clear(Calendar.ZONE_OFFSET);
    cal.setTimeZone(TimeZone.getTimeZone("UTC"));
    long testCalTwo = cal.getTimeInMillis();

    Calendar cal2 = new GregorianCalendar(2000, 0, 1);
    cal2.setTimeZone(TimeZone.getTimeZone("UTC"));
    long testCalThree = cal2.getTimeInMillis();

    System.out.println(testCalOne + ", " + testCalTwo + ", " + testCalThree);

Gives:
946681200000, 946684800000, 946684800000

As you would expect. The only thing I had to do is cal.clear(Calendar.ZONE_OFFSET)  before setting time zone.
Anyway, I'd like to repeat the recommendation from comments. If you value your sanity, switch to JodaTime or Java8 date/time.

