We generally prefer to use the Joda-Time library to handle date and time data.
plusHours
, plusDays
etcLocalDate
, LocalTime
etc)toString
/parse
conversions to/from ISO stringsMost introductions and snippets about Joda-Time illustrate the core DateTime
class, which combines a date, time and timezone.
DateTime now = new DateTime(2015, 4, 13, 9, 15, 0); // use default timezone
DateTime laterToday = now.withTime(17, 30, 0, 0);
DateTime tomorrow = now.plusDays(1);
DateTime muchLater = now.plusMonths(6);
Date + Time + Timezone ⇌ Instant (epoch millis)
Date + Time + Timezone ⇌ Instant (epoch millis)
What is the corresponding instant to 2015-03-29T01:30:00
in Europe/London
timezone?
How about 2015-10-25T01:30:00
?
DateTime dt = new DateTime(2014, 12, 31, 11, 24, 15); // Europe/London
// dt.toString() : "2014-12-31T11:24:15.000Z"
DateTime dt2 = DateTime.parse("2014-12-31T11:24:15Z");
// dt2.toString() : "2014-12-31T11:24:15.000Z"
DateTime dt = new DateTime(2015, 4, 13, 9, 15, 0); // Europe/London
// dt.toString() : "2015-04-13T09:15:00.000+01:00"
DateTime dt2 = DateTime.parse("2015-04-13T09:15:00+01:00");
// dt2.toString() : "2015-04-13T09:15:00.000+01:00"
assertThat(new DateTime(2008, 6, 1, 14, 0, 0) /* Europe/London */,
equalTo(DateTime.parse("2008-06-01T14:00:00+01:00")));
Expected: <2008-06-01T14:00:00.000+01:00> but: was <2008-06-01T14:00:00.000+01:00>
what
These DateTime instances do represent the same time instant, with the same time zone offset, but not the same time zone ruleset.
Parsing a time with +01:00
or Z
as a suffix resolves to a fixed-offset "time zone".
Unfortunately the ruleset isn't clearly indicated in the toString() output, so it's easy to miss the distinction.
There is in fact an org.joda.time.Instant
class. This purely encapsulates an instant, free of any concept of timezone.
assertThat(new DateTime(2008, 6, 1, 14, 0, 0).toInstant(),
equalTo(Instant.parse("2008-06-01T14:00:00+01:00")));
This is likely a more suitable type to correspond to timestamps in databases, event structures...
Instant
does not have those oh-so-convenient plusDays
, plusHours
etc methods.
You have to convert to DateTime
to do that sort of manipulation.
This pushes you to supply a timezone context.
Instant
will be formatted as UTC by a DateTimeFormatter
unless that formatter has an override zone.
Arguably not a bad thing, but not what I expected.
Also has Instant
, and emphasises separation of machine-timeline with human date/times more strictly.
DateTime
becomes ZonedDateTime
and/or OffsetDateTime
, emphasising what they contain.
ZonedDateTime
includes the time zone ruleset name in its toString()
if it is not a fixed offset.
As per Colebourne's blog entry, DateTime
implementing
ReadableInstant
has come to be seen as a mistake (#1 on the list).