tl;dr
how I can do this conversion perfectly for all timezones of USA.
Instant now = Instant.now() ; // Capture current moment in UTC.
ZonedDateTime zdtLosAngeles = now.atZone( ZoneId.of( "America/Los_Angeles" ) ) ;
ZonedDateTime zdtChicago = now.atZone( ZoneId.of( "America/Chicago" ) ) ;
ZonedDateTime zdtNewYork = now.atZone( ZoneId.of( "America/New_York" ) ) ;
ZonedDateTime zdtGuam = now.atZone( ZoneId.of( "America/Guam" ) ) ;
ZonedDateTime zdtHonolulu = now.atZone( ZoneId.of( "America/Los_Angeles" ) ) ;
ZonedDateTime zdtAnchorage = now.atZone( ZoneId.of( "America/Anchorage" ) ) ;
ZonedDateTime zdtIndianapolis = now.atZone( ZoneId.of( "America/Indiana/Indianapolis" ) ) ;
ZonedDateTime zdtPortOfSpain = now.atZone( ZoneId.of( "America/Port_of_Spain" ) ) ;
ZonedDateTime zdtPhoenix = now.atZone( ZoneId.of( "America/Phoenix" ) ) ;
… and so on through the list of the many time zones in the United States.
Date
is UTC
"CURRENT in PST : " + new Date()
This is incorrect; this code is not behaving as you apparently are expecting. You may get a String such as Wed Jun 13 15:58:37 PDT 2018
, or you may not.
A java.util.Date
is always in UTC, by definition. Defined as a count of milliseconds since the epoch reference of first moment of 1970 in UTC. You generated output string may be in west coast time, but that is only by accident.
The confusing part is that the Date::toString
method is unfortunately designed to inject the JVM’s current default time zone dynamically while generating a String to represent this Date
object’s value. If your JVM happens to have a current default time zone of a zone such as America/Los_Angeles
, you will get a string with a west coast US time-of-day. But then your results will vary at runtime should the default time zone be set otherwise, and your "CURRENT in PST:" label will be incorrect. And remember that the JVM’s current default time zone can be changed at any moment during runtime by any code in any thread of any app within the JVM.
The legacy date-time classes are riddled with such poor design choices. Avoid using these classes.
java.time
The modern approach uses the java.time classes rather than those troublesome old legacy date-time classes.
Instant
replaces java.util.Date
. 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() ; // Capture the current moment in UTC.
Apply a time zone (ZoneId
) to get a ZonedDateTime
object. Same moment, same point on the timeline, but viewed through the wall-clock time used by the people of a certain region.
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 pseudo-zones such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
As a shortcut, you can skip the Instant
object by calling ZonedDateTime.now
and passing a ZoneId
.
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
And how I can do this conversion perfectly for all timezones of USA.
Firstly, never use the pseudo-zones “PST”, “CST”, “EST” is discussed above. Use real time zones.
There are many more than three zones in the United States, such as America/Chicago
, America/New_York
, America/Fort_Wayne
, Pacific/Honolulu
, America/Puerto_Rico
, and so on. Why so many? Because current and past practices have varied. For example, some places in the US opt out of the silliness of Daylight Saving Time (DST). Various places have various histories where the offset-from-UTC in that zone were changed by people at different points in their history.
Secondly, keep your time zone definitions up-to-date. Most software systems use a copy of tzdata (formerly known as Olson Database) published by IANA. Your host OS, your JVM implementation, and your database server, likely all have a copy of tzdata that must be kept up-to-date if the rules for any zone you care about change.
Never ignore zone/offset
"yyyy-MM-dd'T'HH:mm:ss'Z'"
Your formatting pattern made a dreadful choice in putting single-quote marks around the Z
. That Z
means UTC, and is pronounced Zulu. Your single-quotes tell the formatter to ignore that particular string as if it were meaningless. But it is not meaningless, it is vital information about your input data which you are choosing to ignore and discard.
Another thing… That particular format is defined by the ISO 8601 standard. The java.time classes use these standard formats by default when parsing/generating strings.
Instant.parse( "2018-01-23T12:34:56Z" ) // Parse standard ISO 8601 string into a `Instant` object.
instant.toString() // Yields "2018-01-23T12:34:56Z".
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.
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?
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.