tl;dr
Instant.parse( "2015-05-24T12:25:15Z" )
.atZone(
ZoneId.of( "America/Montreal" )
)
.toString()
2015-05-24T08:25:15-04:00[America/Montreal]
ZonedDateTime
vs LocalDateTime
Your Question contradicts itself, with the title asking for a ZonedDateTime
and the body asking for a LocalDateTime
. Those are two very different beasts. One (ZonedDateTime
) is a specific moment on the timeline, the other (LocalDateTime
) is only a vague idea about possible moments but is not a specific moment.
For example, the LocalDateTime
of Christmas starting this year is 2017-12-25T00:00:00
but that has no meaning until you apply a time zone as Santa delivers first to the islands of Kiribati at their midnight (the first midnight on Earth), then on to New Zealand at their later midnight, then on to Australia at their later midnight, and so on moving westward toward successive midnights.
Also, you Question seems confused about exactly what is the input and what is the output.
a java.time.LocalDateTime which is in UTC.
This is a contradiction in terms. The LocalDateTime
class lacks any concept of time zone or offset-from-UTC. So this class cannot be used to represent a moment such as a UTC value. For a moment in UTC, use either Instant
or OffsetDateTime
classes.
Instant
For an input like 2015-05-24T12:25:15Z
, that represents a moment on the timeline in UTC (Z
is short for Zulu
and means UTC). To represent that, 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.parse( "2015-05-24T12:25:15Z" );
Generally you should be working in UTC for most business logic, data storage, data exchange, and database. So for that Instant
is all you need.
ZonedDateTime
If you need to adjust into a time zone, such as for presentation to a user, 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( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
LocalDate
If you have a date-only value, parse as a LocalDate
object.
LocalDate localDate = LocalDate.parse( "2002-09-24" );
To get the first moment of the day for that date, specify a time zone. For any given moment, the date varies around the world by zone.
Also, do not assume the day starts at the time of 00:00:00
. Anomalies such as Daylight Saving Time (DST) may cause the first moment to be something like 01:00:00
. Let java.time determine the first moment’s time-of-day.
ZonedDateTime zdt = localDate.atStartOfDay( z );
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.
LocalDateTime
purposely lacks any info about time zone or offset-from-UTC. There is no need to ignore or dispose of that vital info in this situation. Also, you are implicitly applying the JVM’s current default time zone with your call toatStartOfDay
. So results will vary by whatever the current default time zone may be. – Miquelmiquela