new java.util.Date()
as much as possible and avoid java.util.Calendar
like the plague. This works out, more or less, until you need to account for time zones. Java dates don't include any time zone related methods so it's easy to ignore them, we forget that dates really have a time zone of Greenwich Mean Time (GMT).The thing to remember is that a Java date is a very simple object . If you remove the deprecated constructors and methods there is not much left besides
equals(), hashCode()
and getTime()
. A date is really just a wrapper around a Java long integer value and that long integer is the number of milliseconds since January 1, 1970, 00:00:00 GMT. We forget about the GMT business because whenever we print a date it looks like this -Sun Jul 15 10:00:00 CDT 2007
It is easy to forget that the output of
toString()
is the value of the date in a localized format for display and not the real value. The same date printed in two different time zones would look different even though the actual long integer value is the same. Here is an example that may help -
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class CalendarTimeZoneTest {
private static String getCalendarDate(Calendar cal) {
return (cal.get(Calendar.MONTH) + 1) + "/" +
cal.get(Calendar.DAY_OF_MONTH) + "/" +
cal.get(Calendar.YEAR) + " " +
cal.get(Calendar.HOUR_OF_DAY) + ":" +
cal.get(Calendar.MINUTE) + ":" +
cal.get(Calendar.SECOND);
}
private static Calendar getCalendarForTimeZone(TimeZone tz) {
Calendar cal = new GregorianCalendar(tz);
cal.clear();
cal.set(Calendar.HOUR_OF_DAY, 10);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MONTH, 6);
cal.set(Calendar.YEAR, 2007);
cal.set(Calendar.DAY_OF_MONTH, 15);
return cal;
}
private static void showDate(Calendar Cal) {
System.out.println(" Time zone : " +
Cal.getTimeZone().getDisplayName());
System.out.println(" Milliseconds : " +
Cal.getTimeInMillis());
System.out.println(" Calendar Date: " +
getCalendarDate(Cal));
System.out.println(" Local Date : " +
new Date(Cal.getTimeInMillis()));
System.out.println();
}
public static void main(String[] args) {
Calendar localCal =
getCalendarForTimeZone(TimeZone.getTimeZone("America/Chicago"));
Calendar japanCal =
getCalendarForTimeZone(TimeZone.getTimeZone("Japan"));
System.out.println("Same date/time in different time zones");
showDate(localCal);
showDate(japanCal);
System.out.println();
japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan"));
japanCal.setTimeInMillis(localCal.getTimeInMillis());
System.out.println("Same milliseconds in different time zones");
showDate(localCal);
showDate(japanCal);
}
First the example creates two calendars with the same date and time for two different time zones. This results in two dates with different millisecond values. Next, the example creates two calendars with the same milliseconds in two different time zones. The output looks like -
Same date/time in different time zones
Time zone : Central Standard Time
Milliseconds : 1184511600000
Calendar Date: 7/15/2007 10:0:0
Local Date : Sun Jul 15 10:00:00 CDT 2007
Time zone : Japan Standard Time
Milliseconds : 1184461200000
Calendar Date: 7/15/2007 10:0:0
Local Date : Sat Jul 14 20:00:00 CDT 2007
Same milliseconds in different time zones
Time zone : Central Standard Time
Milliseconds : 1184511600000
Calendar Date: 7/15/2007 10:0:0
Local Date : Sun Jul 15 10:00:00 CDT 2007
Time zone : Japan Standard Time
Milliseconds : 1184511600000
Calendar Date: 7/16/2007 0:0:0
Local Date : Sun Jul 15 10:00:00 CDT 2007
What I hope the example demonstrates is that the same Java date, i.e. millisecond value, has different meanings in different time zones. If you want the same date and time in different time zones you must take the offset between time zones into account. The easiest way to do this using the standard Java libraries is to create a date from its parts, year, month, day, etc., using a Java calendar object.