Calendar returns date in wrong time zone
Solution 1:
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.
Solution 2:
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
Solution 3:
When converting the Calendar object to a Date object the timezone is lost. Calendar itself uses the timezone. The following prints to the specified timezone.
TimeZone timeZone = TimeZone.getTimeZone('IST'); // India Standard Time
Calendar calendar = Calendar.getInstance(timeZone);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH) + "/" +
(calendar.get(Calendar.MONTH)+1) + "/" + calendar.get(Calendar.YEAR) + " Time: " +
calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE));
System.out.println(calendar.getTime());
(Note do not use the Calendar API like this, its very messy. Use the date formatting api)
The Date api has many issues (that's why its been completely redone in java 8).