Reputation: 236
See the following piece of code:
String timeString = "1980-01-01T14:00:00+0300";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date2 = sdf.parse(timeString);
// sdf.getCalendar().get(Calendar.ZONE_OFFSET);
System.out.println(sdf.format(date2));
now, I'm in a country that has +2h
offset, +1
daylight savings(at the moment).
If I run this code as it is, it will print
1980-01-01T13:00:00+0200
If I uncomment the line asking about the calendar's offset, the output of the program is
1980-01-01T14:00:00+0300
Any idea why is that happening, and how can I get a consistent output?
To avoid any more unclear things: Since I'm handling some legacy code, java 8 is not an option. And yes, the key point here is WHY, and not what are the workarounds? And there are 2 WHYs:
Upvotes: 7
Views: 150
Reputation: 3736
SimpleDateFormate uses Calendar to create the Date. The Date-Object is created with the Timestamp, wich is Calculated in java.util.GregorianCalendar.computeTime()
. There in Line 2789 the initial time zone is used (which got set java.text.SimpleDateFormat.initializeCalendar(Locale)
). Thats why you see the wrong Timezone.
When you call get(Calendar.ZONE_OFFSET)
the Method java.util.GregorianCalendar.computeFields()
is called, which uses the Timezone that was set initially.
I Guess this is a Bug.
Upvotes: 0
Reputation: 135992
sdf.parse
changes formatter's internal calendar zone offset to +0300
System.out.println(sdf.getCalendar());
sdf.parse(timeString);
System.out.println(sdf.getCalendar());
you can see the difference at the end of output lines
... ,ZONE_OFFSET=7200000,DST_OFFSET=0]
... ,ZONE_OFFSET=10800000,DST_OFFSET=0]
sdf.getCalendar().get(Calendar.ZONE_OFFSET);
restores calendar's zone offset back to current timezone
Upvotes: 0
Reputation: 16041
The problem is, that Calendar#get
is not a simple getter, it looks like this:
public int get(int field)
{
complete();
return internalGet(field);
}
where complete
does this, according to the Javadoc:
Fills in any unset fields in the calendar fields. First, the
computeTime()
method is called if the time value (millisecond offset from the Epoch) has not been calculated from calendar field values. Then, thecomputeFields()
method is called to calculate all calendar field values.
I looked up the source here, but the code is the same for the latest Java version too.
Upvotes: 2