I have an issue where I tried all ways(including online stackoverflow threads), but am not able to set timezone as expected on a specific date. Here's my code:
Date until = DateTimeUtils.getNewBookUntilDate();
//which returns : Wed Aug 28 11:00:02 EDT 2019
SimpleDateFormat isoFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
isoFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles");
try {
until = isoFormat.parse(until.toString());
} catch (ParseException e) {
e.printStackTrace();
}
But I still get : Wed Aug 28 11:00:02 EDT 2019 , instead of Wed Aug 28 8:00:02 PDT 2019
Any idea how to go about this?
Avoid java.util.Date
A java.util.Date
represents a moment in UTC. No need to manipulate it as text. Beware: the method Date::toString
tells a lie, dynamically applying the JVM’s current default time zone while generating the text.
Instead, use java.time.Instant
First convert from that terrible legacy class to its modern replacement, java.time.Instant
. Notice the new conversion methods added to the old classes.
Instant instant = myDate.toInstant() ;
ZonedDateTime
An Instant
is also a moment in UTC. To see that same moment through the offset-from-UTC used by the people of a certain region, apply a ZoneId
to get a ZonedDateTime
object.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Be clear: This zdt
object and this instant
object both represent the same moment, the same point on the timeline. They are different only in the wall-clock time. Imagine someone in Iceland (always in UTC) calling someone in Québec, and they both look up at the clock on their respective walls.
Converting from modern to legacy
If you have a ZonedDateTime
object in hand, and you must get a java.util.Date
for interoperating with old code not yet updated to java.time, you can convert. Go from an Instant
to a Date
, by extracting a Instant
from your ZonedDateTime
object.
Instant instant = zdt.toInstant() ;
java.util.Date date = java.util.Date.from ( instant ) ;
If you need a Calendar
rather than Date
, the conversion is more direct.
Calendar cal = GregorianCalendar.from( zdt ) ;
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
.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….