FULL PRODUCT VERSION :
java version "1.4.2_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_02-b03)
Java HotSpot(TM) Client VM (build 1.4.2_02-b03, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]
A DESCRIPTION OF THE PROBLEM :
If you sett a Calendar's field ZONE_OFFSET and immediately query it, the value returned is always the offset of the Calendar's TimeZone, i.e., the instance which can be accessed via getTimeZone(). I'd expect that the invocation of a get() method does not change the state of an instance visibly.
I suspect GregorianCalendar.computeFields() as the culprit., because that method seems to ignore a user set ZONE_OFFSET.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the example below and run it.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Output (see actual result) should include no lines beginning with "Offset mismatch!" and the two timestamps printed for a single offset should be identical. Invoking Calendar.get() should not change the visible state of the instance.
ACTUAL -
Hour offset: -24
Dienstag, 5. Juni 2001 1.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -24
Hour offset: -23
Dienstag, 5. Juni 2001 0.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -23
Hour offset: -22
Montag, 4. Juni 2001 23.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -22
Hour offset: -21
Montag, 4. Juni 2001 22.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -21
Hour offset: -20
Montag, 4. Juni 2001 21.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -20
Hour offset: -19
Montag, 4. Juni 2001 20.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -19
Hour offset: -18
Montag, 4. Juni 2001 19.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -18
Hour offset: -17
Montag, 4. Juni 2001 18.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -17
Hour offset: -16
Montag, 4. Juni 2001 17.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -16
Hour offset: -15
Montag, 4. Juni 2001 16.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -15
Hour offset: -14
Montag, 4. Juni 2001 15.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -14
Hour offset: -13
Montag, 4. Juni 2001 14.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -13
Hour offset: -12
Montag, 4. Juni 2001 13.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -12
Hour offset: -11
Montag, 4. Juni 2001 12.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -11
Hour offset: -10
Montag, 4. Juni 2001 11.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -10
Hour offset: -9
Montag, 4. Juni 2001 10.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -9
Hour offset: -8
Montag, 4. Juni 2001 9.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -8
Hour offset: -7
Montag, 4. Juni 2001 8.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -7
Hour offset: -6
Montag, 4. Juni 2001 7.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -6
Hour offset: -5
Montag, 4. Juni 2001 6.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -5
Hour offset: -4
Montag, 4. Juni 2001 5.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -4
Hour offset: -3
Montag, 4. Juni 2001 4.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -3
Hour offset: -2
Montag, 4. Juni 2001 3.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -2
Hour offset: -1
Montag, 4. Juni 2001 2.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: -1
Hour offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 0
Hour offset: 1
Montag, 4. Juni 2001 0.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 1
Hour offset: 2
Sonntag, 3. Juni 2001 23.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 2
Hour offset: 3
Sonntag, 3. Juni 2001 22.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 3
Hour offset: 4
Sonntag, 3. Juni 2001 21.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 4
Hour offset: 5
Sonntag, 3. Juni 2001 20.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 5
Hour offset: 6
Sonntag, 3. Juni 2001 19.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 6
Hour offset: 7
Sonntag, 3. Juni 2001 18.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 7
Hour offset: 8
Sonntag, 3. Juni 2001 17.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 8
Hour offset: 9
Sonntag, 3. Juni 2001 16.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 9
Hour offset: 10
Sonntag, 3. Juni 2001 15.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 10
Hour offset: 11
Sonntag, 3. Juni 2001 14.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 11
Hour offset: 12
Sonntag, 3. Juni 2001 13.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 12
Hour offset: 13
Sonntag, 3. Juni 2001 12.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 13
Hour offset: 14
Sonntag, 3. Juni 2001 11.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 14
Hour offset: 15
Sonntag, 3. Juni 2001 10.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 15
Hour offset: 16
Sonntag, 3. Juni 2001 9.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 16
Hour offset: 17
Sonntag, 3. Juni 2001 8.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 17
Hour offset: 18
Sonntag, 3. Juni 2001 7.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 18
Hour offset: 19
Sonntag, 3. Juni 2001 6.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 19
Hour offset: 20
Sonntag, 3. Juni 2001 5.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 20
Hour offset: 21
Sonntag, 3. Juni 2001 4.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 21
Hour offset: 22
Sonntag, 3. Juni 2001 3.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 22
Hour offset: 23
Sonntag, 3. Juni 2001 2.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 23
Hour offset: 24
Sonntag, 3. Juni 2001 1.02 Uhr UTC
Offset mismatch! Current offset: 0
Montag, 4. Juni 2001 1.02 Uhr UTC
difference: 24
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.text.DateFormat;
import java.util.*;
/**
* Test class to demonstrate inconsistency in Calendar due to invocation of get
* method.
*
* @author robert.klemme
* @created 16.09.2004 15:41:26
* @version $Id:$
*/
public class TimeZoneDemo {
private static final int MS_PER_HR = 1000 * 60 * 60;
public static void main( String[] args ) {
final DateFormat formatter = DateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL );
final TimeZone UTC = TimeZone.getTimeZone( "UTC" );
final Calendar printCalendar = Calendar.getInstance( UTC );
formatter.setCalendar( printCalendar );
final Calendar calendarToSet = Calendar.getInstance( UTC, Locale.US );
for ( int hours = -24; hours <= 24; ++hours ) {
System.out.println( "Hour offset: " + hours );
final int offsetToSet = hours * MS_PER_HR;
// first attempt succeeds
calendarToSet.set( Calendar.ZONE_OFFSET, offsetToSet );
// don't query offset here!
setValues( calendarToSet );
final long timeOk = calendarToSet.getTimeInMillis();
System.out.println( formatter.format( calendarToSet.getTime() ) );
// second attempt fails due to get() invocation
// "parseCal.get( Calendar.ZONE_OFFSET )" is the offending expression
calendarToSet.set( Calendar.ZONE_OFFSET, offsetToSet );
final int currentOffset = calendarToSet.get( Calendar.ZONE_OFFSET );
if ( offsetToSet != currentOffset ) {
System.err.println( "Offset mismatch! Current offset: " + ( currentOffset / MS_PER_HR ) );
}
setValues( calendarToSet );
final long timeErr = calendarToSet.getTimeInMillis();
System.out.println( formatter.format( calendarToSet.getTime() ) );
System.err.println( "difference: " + ( ( timeErr - timeOk ) / MS_PER_HR ) );
System.out.println();
}
}
/**
* Set calendar field values to fixed values.
*
* @param parseCal the calendar to update.
*/
private static void setValues( final Calendar parseCal ) {
parseCal.set( Calendar.HOUR_OF_DAY, 1 );
parseCal.set( Calendar.MINUTE, 2 );
parseCal.set( Calendar.SECOND, 3 );
parseCal.set( Calendar.DAY_OF_MONTH, 4 );
parseCal.set( Calendar.MONTH, 5 );
parseCal.set( Calendar.YEAR, 2001 );
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Never try to verify that the zone offset you set is the one that you get in return.