Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calendar returns date in wrong time zone

If I execute the following on a computer in the GMT timezone

TimeZone timeZone = TimeZone.getTimeZone('IST');  // India Standard Time
Calendar calendar = Calendar.getInstance(timeZone);

System.out.println(calendar.getTime());

It prints

Fri Oct 31 15:18:22 GMT 2014

Why is the date printed in the computer's default time zone, rather than the TimeZone the Calendar was constructed with?

like image 685
Dónal Avatar asked Oct 31 '14 15:10

Dónal


2 Answers

The Answer by Joshi is correct but brief. I'll expand a bit, and show an alternative with modern classes.

Date has no time zone

Your code calendar.getTime() extracts a java.util.Date object from the java.util.Calendar object.

The java.util.Date class has a well-intentioned but confusing feature where its toString method applies the JVM’s current default time zone while generating the string. This creates the illusion that the Date class has a time zone when it does not. A Date represents a moment on the timeline as a count of milliseconds since the epoch reference date of first moment of 1970 UTC (1970-01-01T00:00:00Z). (Even more confusing, the Date class actually does have a time zone nestled deep inside, but is unreachable and irrelevant to this discussion.)

Avoid legacy date-time classes

The old date-time classes are now legacy, supplanted by the java.time classes. Instead use only the java.time classes.

Instant

For a moment in UTC, the equivalent to java.util.Date, use the Instant class. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.now();  // Current moment in UTC.

ZonedDateTime

To view the same moment through the lens of a particular region’s wall-clock time, apply a ZoneId to get a ZonedDateTime.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = instant.atZone( z );

Search Stack Overflow for many other Questions and Answers on this topic. This Question is really a duplicate of many others.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

  • Java SE 8 and SE 9 and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
    • See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

like image 69
Basil Bourque Avatar answered Oct 04 '22 01:10

Basil Bourque


because Date object doesn't have timezone as part of its state, You need SimpleDateFormat to format and print the date in your required timezone

like image 34
jmj Avatar answered Oct 04 '22 01:10

jmj