We’re sorry. We could not find a match for your search.
We suggest you try the following to help find what you’re looking for:
Check the spelling of your keyword search.
Use synonyms for the keyword you typed, for example, try "application" instead of "software."
Start a new search.
For example, the existing classes (such as
java.util.Date
and
SimpleDateFormatter
) aren’t thread-safe, leading to potential concurrency issues for users—not something the average developer would expect to deal with when writing date-handling code.
Some of the date and time classes also exhibit quite poor API design. For example, years in
java.util.Date
start at 1900, months start at 1, and days start at 0—not very intuitive.
These issues, and several others, have led to the popularity of third-party date and time libraries, such as Joda-Time.
In order to address these problems and provide better support in the JDK core, a new date and time API, which is free of these problems, has been designed for Java SE 8.
The project has been led jointly by the author of Joda-Time (Stephen Colebourne) and Oracle, under JSR 310, and will appear in the new Java SE 8 package
java.time
.
Core Ideas
The new API is driven by three core ideas:
-
Immutable-value classes.
One of the serious weaknesses of the existing formatters in Java is that they aren’t thread-safe. This puts the burden on developers to use them in a thread-safe manner and to think about concurrency problems in their day-to-day development of date-handling code. The new API avoids this issue by ensuring that all its core classes are immutable and represent well-defined values.
-
Domain-driven design.
The new API models its domain very precisely with classes that represent different use cases for
Date
and
Time
closely. This differs from previous Java libraries that were quite poor in that regard. For example,
java.util.Date
represents an instant on the timeline—a wrapper around the number of milli-seconds since the UNIX epoch—but if you call
toString()
, the result suggests that it has a time zone, causing confusion among developers.
This emphasis on domain-driven design offers long-term benefits around clarity and understandability, but you might need to think through your application’s domain model of dates when porting from previous APIs to Java SE 8.
-
Separation of chronologies.
The new API allows people to work with different calendaring systems in order to support the needs of users in some areas of the world, such as Japan or Thailand, that don’t necessarily follow ISO-8601. It does so without imposing additional burden on the majority of developers, who need to work only with the standard chronology.
LocalDate and LocalTime
The first classes you will probably encounter when using the new API are
LocalDate
and
LocalTime
. They are local in the sense that they represent date and time from the context of the observer, such as a calendar on a desk or a clock on your wall. There is also a composite class called
LocalDateTime
, which is a pairing of
LocalDate
and
LocalTime
.
Time zones, which disambiguate the contexts of different observers, are put to one side here; you should use these local classes when you don’t need that context. A desktop JavaFX application might be one of those times. These classes can even be used for representing time on a distributed system that has consistent time zones.
Creating Objects
All the core classes in the new API are constructed by fluent factory methods. When constructing a value by its constituent fields, the factory is called
of
; when converting from another type, the factory is called
from
. There are also parse methods that take strings as parameters. See Listing 1.
LocalDateTime timePoint = LocalDateTime.now(
); // The current date and time
LocalDate.of(2012, Month.DECEMBER, 12); // from values
LocalDate.ofEpochDay(150); // middle of 1970
LocalTime.of(17, 18); // the train I took home today
LocalTime.parse("10:15:30"); // From a String
Listing 1
Standard Java getter conventions are used in order to obtain values from Java SE 8 classes, as shown in Listing 2.
LocalDate theDate = timePoint.toLocalDate();
Month month = timePoint.getMonth();
int day = timePoint.getDayOfMonth();
timePoint.getSecond();
Listing 2
You can also alter the object values in order to perform calculations. Because all core classes are immutable in the new API, these methods are called
with
and return new objects, rather than using setters (see Listing 3). There are also methods for calculations based on the different fields.
// Set the value, returning a new object
LocalDateTime thePast = timePoint.withDayOfMonth(
10).withYear(2010);
/* You can use direct manipulation methods,
or pass a value and field pair */
LocalDateTime yetAnother = thePast.plusWeeks(
3).plus(3, ChronoUnit.WEEKS);
Listing 3
The new API also has the concept of an
adjuster
—a block of code that can be used to wrap up common processing logic. You can either write a
WithAdjuster
, which is used to set one or more fields, or a
PlusAdjuster
, which is used to add or subtract some fields. Value classes can also act as adjusters, in which case they update the values of the fields they represent. Built-in adjusters are defined by the new API, but you can write your own adjusters if you have specific business logic that you wish to reuse. See Listing 4.
import static java.time.temporal.TemporalAdjusters.*;
LocalDateTime timePoint = ...
foo = timePoint.with(lastDayOfMonth());
bar = timePoint.with(previousOrSame(ChronoUnit.WEDNESDAY));
// Using value classes as adjusters
timePoint.with(LocalTime.now());
Listing 4
Truncation
The new API supports different precision time points by offering types to represent a date, a time, and date with time, but obviously there are notions of precision that are more fine-grained than this.
The
truncatedTo
method exists to support such use cases, and it allows you to truncate a value to a field, as shown in Listing 5.
LocalTime truncatedTime = time.truncatedTo(ChronoUnit.SECONDS);
Listing 5
Time Zones
The local classes that we looked at previously abstract away the complexity introduced by time zones. A time zone is a set of rules, corresponding to a region in which the standard time is the same. There are about 40 of them. Time zones are defined by their offset from Coordinated Universal Time (UTC). They move roughly in sync, but by a specified difference.
Time zones can be referred to by two identifiers: abbreviated, for example, “PLT,” and longer, for example, “Asia/Karachi.” When designing your application, you should consider what scenarios are appropriate for using time zones and when offsets are appropriate.
-
ZoneId
is an identifier for a region (see Listing 6). Each
ZoneId
corresponds to some rules that define the time zone for that location. When designing your software, if you consider throwing around a string such as “PLT” or “Asia/Karachi,” you should use this domain class instead. An example use case would be storing users’ preferences for their time zone.
// You can specify the zone id when creating a zoned date time
ZoneId id = ZoneId.of("Europe/Paris");
ZonedDateTime zoned = ZonedDateTime.of(dateTime, id);
assertEquals(id, ZoneId.from(zoned));
Listing 6
-
ZoneOffset
is the period of time representing a difference between Greenwich/UTC and a time zone. This can be resolved for a specific
ZoneId
at a specific moment in time, as shown in Listing 7.
ZoneOffset offset = ZoneOffset.of("+2:00");
Listing 7
Time Zone Classes
-
ZonedDateTime
is a date and time with a fully qualified time zone (see Listing 8). This can resolve an offset at any point in time. The rule of thumb is that if you want to represent a date and time without relying on the context of a specific server, you should use
ZonedDateTime
.
ZonedDateTime.parse("2007-12-03T10:15:30+01:00[Europe/Paris]");
Listing 8
-
OffsetDateTime
is a date and time with a resolved offset. This is useful for serializing data into a database and also should be used as the serialization format for logging time stamps if you have servers in different time zones.
-
OffsetTime
is a time with a resolved offset, as shown in Listing 9.
OffsetTime time = OffsetTime.now();
// changes offset, while keeping the same point on the timeline
OffsetTime sameTimeDifferentOffset = time.withOffsetSameInstant(
offset);
// changes the offset, and updates the point on the timeline
OffsetTime changeTimeWithNewOffset = time.withOffsetSameLocal(
offset);
// Can also create new object with altered fields as before
changeTimeWithNewOffset
.withHour(3)
.plusSeconds(2);
Listing 9
There is an existing time zone class in Java—
java.util.TimeZone
—but it isn’t used by Java SE 8 be-cause all JSR 310 classes are immutable and time zone is mutable.
Periods
A
Period
represents a value such as “3 months and 1 day,” which is a distance on the timeline. This is in contrast to the other classes we’ve looked at so far, which have been points on the timeline. See Listing 10.
// 3 years, 2 months, 1 day
Period period = Period.of(3, 2, 1);
// You can modify the values of dates using periods
LocalDate newDate = oldDate.plus(period);
ZonedDateTime newDateTime = oldDateTime.minus(period);
// Components of a Period are represented by ChronoUnit values
assertEquals(1, period.get(ChronoUnit.DAYS));
Listing 10
Durations
A
Duration
is a distance on the timeline measured in terms of time, and it fulfills a similar purpose to
Period
, but with different precision, as shown in Listing 11.
// A duration of 3 seconds and 5 nanoseconds
Duration duration = Duration.ofSeconds(3, 5);
Duration oneDay = Duration.between(today, yesterday);
Java SE 8 will ship with a new date and time API in java.time
that offers greatly improved safety and functionality for developers. The new API models the domain well, with a good selection of classes for modeling a wide variety of developer use cases.
Listing 11
It’s possible to perform normal plus, minus, and “with” operations on a
Duration
instance and also to modify the value of a date or time using the
Duration
.
Chronologies
In order to support the needs of developers using non-ISO calendaring systems, Java SE 8 introduces the concept of a
Chronology
, which represents a calendaring system and acts as a factory for time points within the calendaring system. There are also interfaces that correspond to core time point classes, but are parameterized by
Chronology:
ChronoLocalDate
ChronoLocalDateTime
ChronoZonedDateTime
These classes are there purely for developers who are working on highly internationalized applications that need to take into account local calendaring systems, and they shouldn’t be used by developers without these requirements. Some calendaring systems don’t even have a concept of a month or a week and calculations would need to be performed via the very generic field API.
The Rest of the API
Java SE 8 also has classes for some other common use cases. There is the
MonthDay
class, which contains a pair of
Month
and
Day
and is useful for representing birthdays. The
YearMonth
class covers the credit card start date and expiration date use cases and scenarios in which people have a date with no specified day.
DATE LocalDate TIME LocalTime TIMESTAMP LocalDateTime TIME WITH TIMEZONE OffsetTime TIMESTAMP WITH TIMEZONE OffsetDateTime
Table 1