A new new infrastructure for time and date handling.
Actually, it's not all that new, it's an evolution of the popular Joda-Time library, accepted into the JDK as JSR-310. Stephen Colebourne, who wrote Joda-Time, is the principal for the JSR.
Terms like "date" and "time" are overloaded, so one aim is to clearly define what terms mean (rule 3).
By these terms, a java.util.Date
is not a date at all.
It's not going away. And if you're not using Java8 or planning to upgrade, you can and probably should go on using it.
However, it's interesting to look at the differences, they can demonstrate perceived deficiencies.
Sometimes they point to changed perceptions in common practices. For example, all java.time value objects are immutable; Joda-Time has mutable versions.
DateTime
is gone
An instant is a point on the timeline, independent of any chronology
A date and time can be used to find an instant- if you have enough context, you can interconvert.
A date, time and zone offset
Joda-Time has Instant
, but have you ever used it? DateTime
implements ReadableInstant
, so basically does everything an Instant
does anyway.
// When is this exactly?
new org.joda.time.DateTime(2015, JANUARY, 14, 2, 3, 4).toMillis()
An instant is the "millis since epoch" (although now to nanosecond precision)
// Provide all the information
java.time.LocalDateTime.of(2015, JANUARY, 14, 2, 3, 4)
.toInstant(ZoneOffset.UTC)
// equivalent:
java.time.OffsetDateTime.of(java.time.LocalDate.of(2015, JANUARY, 14),
java.time.LocalTime.of(2, 3, 4),
ZoneOffset.UTC)
.toInstant()
OffsetDateTime
or ZonedDateTime
essentially replace DateTime
Instant
replaces using a long
(please...)
"Everyone knows" there are 12 months in a year etc., right?
That's not actually always the case. Other chronologies work differently. In java.time, classes like LocalDateTime
are definitely using ISO chronology, though. In Joda-Time, theoretically not...
((org.joda.time.DateTime) datetime).getMonthOfYear() == 13;
// it can happen
((java.time.LocalDateTime) datetime).getMonthValue() == 13;
// never happens
((java.time.LocalDateTime) datetime).getMonth() == Month.DECEMBER;
// now months can be an enum
Help to make working with date/time objects understandable
Period
is a date-based amount (4 days, a week)
Duration
is a time-based amount (2 minutes, 48 hours)
These are examples of temporal amounts.
dateTime.plus(Period.ofMonths(9));
dateTime.minus(Duration.ofSeconds(20));
instant.minus(Duration.ofHours(1));
TemporalAdjuster
objects represent transformations
LocalDate.now().with(TemporalAdjusters.*/next(DayOfWeek.TUESDAY));
date.with(lastDayOfMonth());
date.with(lastDayOfQuarter());
twoDaysLater = TemporalAdjusters.ofDateAdjuster(date -> date.plusDays(2));
ChronoUnit.DAYS.between(then, now)
Year.of(2015).atMonth(Month.JANUARY).atEndOfMonth().atStartOfDay();
(It turns out that some days don't have a midnight...)
java.util.TimeZone represents a zone offset and works out DST rules
java.time splits this into:
ZoneId
ZoneRules
ZoneOffset
extends ZoneId
// what does Joda-Time's DateTime.withTimeZone() do?
offsetDateTime.atZoneSameInstant(ZoneId.of("Europe/London"));
offsetDateTime.atZoneSimilarLocal(ZoneId.of("Europe/London"));
When is Instant.now()
?
Joda-Time has DateTimeUtils
to allow overriding a fixed value
java.time defines a Clock
class to provide the current instant and timezone, for injection
Clock.systemDefaultZone(); // default for LocalDateTime.now()
Clock.systemUTC(); // default for Instant.now()
Clock.system(ZoneId.of(someTzName)); // override default time zone
Clock.fixed(Instant.parse("2015-03-11T23:32:00Z"), ZoneOffset.UTC);
Clock.tickSeconds(UTC); // only tick 1 second at a time
Clock.tick(Clock.systemUTC(), Duration.ofMillis(1L)); // only 1ms
clock.instant(); clock.getZone(); // access the clock