Can someone explain why is SimpleDateFormat substracting 1 second to my parsed date when setting the time zone with SimpleTimeZone?
Is this a jdk bug?
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
public class SimpleDateFormatTest {
public static void main(String[] args) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(format.parse("2016-02-24T17:31:00Z"));
// prints Wed Feb 24 17:31:00 UTC 2016
format.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
System.out.println(format.parse("2016-02-24T17:31:00Z"));
// Wed Feb 24 17:30:59 UTC 2016
}
}
You're using the constructor improperly.
The constructor of SimpleTimeZone
is defined as:
public SimpleTimeZone(int rawOffset, String ID)
Constructs a SimpleTimeZone with the given base time zone offset from GMT and time zone ID with no daylight saving time schedule.
Parameters:
rawOffset
- The base time zone offset in milliseconds to GMT.
ID
- The time zone name that is given to this instance.
So the first parameter to the constructor is how much the time zone you are creating is going to differ from GMT, in milliseconds.
There is no reason to use any of the constants STANDARD_TIME
, UTC_TIME
or WALL_TIME
here. This is not the place for them to be used. However, because these constants are of type int
, and the rawOffset
parameter is of type int
, Java is not preventing you from passing these constant erroneously to the constructor.
In the Java source code, this constant is defined as:
public static final int UTC_TIME = 2;
So what you are actually doing when you call
new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC")
Is saying "Please create a time zone which is 2 milliseconds away from GMT, and call it 'UTC'". I'm pretty sure that this is not what you were trying to achieve. It is a custom time zone, that's a little different than UTC
, and this difference is rounded to a whole second in your output.
The value of SimpleTimeZone.UTC_TIME
is actually 2, so the SimpleTimeZone
is constructed with a two millisecond offset:
/**
* Constant for a mode of start or end time specified as UTC. European
* Union rules are specified as UTC time, for example.
* @since 1.4
*/
public static final int UTC_TIME = 2;
/**
* Constructs a SimpleTimeZone with the given base time zone offset from GMT
* and time zone ID with no daylight saving time schedule.
*
* @param rawOffset The base time zone offset in milliseconds to GMT.
* @param ID The time zone name that is given to this instance.
*/
public SimpleTimeZone(int rawOffset, String ID)
{
this.rawOffset = rawOffset;
setID (ID);
dstSavings = millisPerHour;
}
Ideone test:
public static void main(String[] args) throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date1 = format.parse("2016-02-24T17:31:00Z");
System.out.println(date1.getTime());
format.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
Date date2 = format.parse("2016-02-24T17:31:00Z");
System.out.println(date2.getTime());
}
Results:
1456335060000
1456335059998
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With