tl;dr
Capture input.
Instant instant =
OffsetDateTime.of( LocalDate.of( 2016 , 1 , 2 ) ,
LocalTime.of( 12 , 34 , 56 ) ,
ZoneOffset.ofHours( -3 )
)
.toInstant() ;
Generate output for presentation in any time zone with any Locale
.
String output =
instant.atZone( ZoneId.of( "Pacific/Auckland" ) )
.format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( Locale.CANADA_FRENCH )
) ;
Use proper time zone names
Specify a proper time zone name. 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(!).
Offset versus time zone
An offset-from-UTC is a number of hours and minutes and seconds different from UTC that a particular locality of people use in setting the time on their clocks, the wall-clock time.
A time zone is an offset plus a set of rules for handling anomalies.
So GMT-3
is not your time zone, it is your offset. Your time zone might be America/Buenos_Aires
, Antarctica/Rothera
, or such.
Since a time zone provides more information and more features, always use a time zone in preference over a mere offset.
Tip: Always write out an offset with padding zeros and with both hour and minutes separated by colon. The other variations are permitted by the ISO 8601 standard, but are sometimes not supported in various protocols or software systems. So use -03:00
rather than -3
.
Avoid legacy date-time classes
Do not use the notoriously troublesome old legacy classes bundled with the earliest versions of Java. Avoid java.util.Date
, java.util.Calendar
, SimpleDateFormat
, and such. Now supplanted by the java.time classes.
LocalDate
& LocalTime
The LocalDate
and LocalTime
types in java.time represent a date-only or time-of-day-only value, and without time zone. Use these to collect data from your widgets. “Local” means “un-zoned”, lacking in offset or time zone meaning.
LocalDate ld = LocalDate.of( 2016 , 1 , 2 );
LocalTime lt = LocalTime.of( 12 , 34 , 56 );
OffsetDateTime
If all we have is an offset of three hours rather than a full time zone, interpret that pair of LocalDate
& LocalTime
as a OffsetDateTime
object with a ZoneOffset
object.
ZoneOffset offset = ZoneOffset.ofHours( -3 );
OffsetDateTime odt = OffsetDateTime.of( ld , lt , offset );
ZonedDateTime
If we do have a time zone in mind, apply a ZoneId
to get a ZonedDateTime
.
ZoneId z = ZoneId.of( "America/Buenos_Aires" );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
Instant
Do much of your business logic, data storage, and data exchange in UTC. Apply offset or time zone only where needed such as presentation to the user.
The Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds.
You can extract a Instant
object from the other types.
Instant instant = zdt.toInstant();
Adjust the instant into any other time zones you may desire.
ZonedDateTime zdtNewYork = instant.atZone( ZoneId.of( "America/New_York" ) );
ZonedDateTime zdtParis = instant.atZone( ZoneId.of( "Europe/Paris" ) );
ZonedDateTime zdtAuckland = instant.atZone( ZoneId.of( "Pacific/Auckland" ) );
These objects all represent the same moment, the same point on the timeline. They are different only in that we are viewing the same moment through the lens of each locality’s wall-clock time.
Strings
Keep in mind that strings are not date-time values; they are a representation in text of the date-time value.
So a date-time object can generate a String in any format you desire. You can specify a custom format. But generally best to let java.time automatically localize for you.
To localize, specify:
FormatStyle
to determine how long or abbreviated should the string be.
Locale
to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.
Example:
Locale l = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l );
String output = zdt.format( f );
Note that Locale
is orthogonal to time zone, completely unrelated. You can have a French presentation of an Pacific/Auckland
zoned value, or a Hindu presentation of a Europe/Copenhagen
zoned value.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
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.