Wrong class: LocalDateTime
Never use LocalDateTime
to track an actual moment. Lacking any concept of time zone or offset-from-UTC, a LocalDateTime
cannot represent a moment. A LocalDateTime
can know “noon on the 23rd of January 2019” but it does not know if you mean noon in Tokyo Japan, noon in Tunis Tunisia, or noon in Montréal Québec — three very different moments, each separated by several hours.
The word “Local” in LocalDateTime
means any locality, or every locality. But it does not mean any one particular locality.
Correct class: ZonedDateTime
To track moments use either Instant
(always in UTC) or ZonedDateTime
(or perhaps OffsetDateTime
).
Specify a proper time zone name in the format of Continent/Region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 2-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 = ZonedDateTime.now( z ) ; // Capture the current moment as seen through the wall-clock time used by the people of a particular region (a time zone).
Instant instant = zdt.toInstant() ; // Adjust from a zone to UTC, if needed. An `Instant` is always in UTC by definition.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If critical, confirm the zone with your user.
Auto-localize
The DateTimeFormatter
class can automatically localize while generating text representing the value of date-time object.
To localize, specify:
FormatStyle
to determine how long or abbreviated should the string be.
Locale
to determine:
- The human language for translation of name of day, name of month, and such.
- The cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.
Example:
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.JAPAN, etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( l );
String output = zdt.format( f );
Be clear that locale and time zone have nothing to do with one another – orthogonal issues. A engineer from Québec attending a conference in India might want to see the schedule of events presented in her native French language with Canadian cultural norms, and with the date-times shown in the local Indian time zone.
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?
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.