Java - JVM Timezone

> Procedural Languages > Java > Java - Date / Time

1 - About

3 - Test Class

public static void main(String[] args) {
    System.out.println("Date = " + new Date());
    System.out.println("Calendar = " + Calendar.getInstance());
Date = Sat Nov 21 15:11:17 CET 2015
Calendar = java.util.GregorianCalendar[time=1448115077906,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Berlin",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=143,lastRule=java.util.SimpleTimeZone[id=Europe/Berlin,offset=3600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2015,MONTH=10,WEEK_OF_YEAR=47,WEEK_OF_MONTH=3,DAY_OF_MONTH=21,DAY_OF_YEAR=325,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=3,HOUR_OF_DAY=15,MINUTE=11,SECOND=17,MILLISECOND=906,ZONE_OFFSET=3600000,DST_OFFSET=0]

4 - Other

Java date-time values (java.util.Date, java.sql.Timestamp etc.) represent a moment in time, and their timezone is always UTC.

When you read that value using Timestamp ResultSet.getTimestamp(String) you are implicitly saying “assume that the value is in my JVM's local time zone”.

So, we're looking at the value 1970-01-01 00:00:00 GMT+8 and converting it to a UTC value, which gives -28,800,000.

When it was midnight on 1970-01-01 in China, it was 4pm on 1969-12-31 in Greenwich.

If you've stored my date-time values in UTC, you should specify a time-zone when retrieving, by using a Calendar object.

ResultSet rs;
TimeZone tzUtc   = TimeZone.getTimeZone("UTC");
Calendar cUtc   = Calendar.getInstance(tzUtc);
Timestamp ts = rs.getTimestamp("dateColumn", cUtc);
System.out.println(ts.getTime()); // prints 0

The same timezone-shifting problem can also occur on the way in. Make sure the value in the database really is 0. If it isn't, use PreparedStatement.setTimestamp(0, cUtc) to prevent the shift.