A new Date and Time API for Java. The design includes a relatively large number of classes and methods, however each follows a common design language, especially in method prefixes. Once the prefixes are understood, the API is relatively simple to comprehend.
The Java Time API is composed of several packages, each with a primary function:
{@link java.time} contains the main API based on the ISO-8601 standard. The classes defined here represent the principal date-time concepts, including instants, durations, dates, times, time-zones and periods. They are based on the ISO calendar system, which is the de facto world calendar following the proleptic Gregorian rules. All the classes are immutable and thread-safe.
{@link java.time.temporal} contains the API for accessing the fields and units of date-time. Units are measurable, such as years, months and hours. For example, the expression "2 hours later" uses the hours unit. By contrast, fields are mini-calculations, defining a value. For example, month-of-year, day-of-week and hour-of-day are all fields. The set of supported units and fields can be extended by applications if desired.
{@link java.time.format} contains the API to print and parse fields into date-time objects and to customize parsing and printing. Formatters can be created in a variety of ways, including constants, patterns, localized styles and a builder. Formatters are immutable and thread-safe.
{@link java.time.zone} contains the API to handle time-zones. Detailed information is made available about the rules of each time-zone.
{@link java.time.chrono} contains the basic part of the calendar neutral API and alternate calendar systems. This is intended for use by applications that need to use localized calendars. Support is provided for the Hijrah, Japanese, Minguo, and Thai Buddhist Calendars.
Where possible, the API avoids the use of null. All methods define whether they accept or return null in the Javadoc. As a general rule, methods do not accept or return null. A key exception is any method that takes an object and returns a boolean, for the purpose of checking or validating, will generally return false for null.
The API is designed to be type-safe where reasonable in the main high-level API. Thus, there are separate classes for the distinct concepts of date, time and date-time, plus variants for offset and time-zones. The core 7 date-time classes, plus Instant, handle the needs of most applications. Further classes handle other combinations - year, year-month and month-day in a type-safe manner.
In a language like Java, the use of many different types tends to cause API bloat. This is handled here through the use of common method naming patterns throughout the API. The common prefixes are 'of', 'get', 'is', 'with', 'plus', 'minus', 'to' and 'at'. See {@link java.time.LocalDate} for an example of each of these methods.
Following type-safety to its logical conclusion would result in more classes, especially for time - hour-minute, hour-minute-second and hour-minute-second-nanosecond. While logically pure, this was not possible in practice, as the additional classes would have excessively complicated the API. Notably, there would be additional combinations at the offset and date-time levels, such as offset-date-hour-minute. To avoid this explosion of types, {@link java.time.LocalTime} is used for all precisions of time. By contrast, some additional classes were used for dates, such as {@link java.time.YearMonth}. This proved necessary, as the API for year-month is significantly different to that for a date, whereas an absence of nanoseconds in a time can be approximated by returning zero.
Similarly, full type-safety might argue for a separate class for each field in date-time, such as a class for HourOfDay and another for DayOfMonth. This approach was tried, but was excessively complicated in the Java language, lacking usability. A similar problem occurs with periods. There is a case for a separate class for each period unit, such as a type for Years and a type for Minutes. However, this yields a lot of classes and a problem of type conversion. As such, general access to fields and units is not wrapped in a class.
Multiple calendar systems is an awkward addition to the design challenges. The first principal is that most users want the standard ISO calendar system. As such, the main classes are ISO-only. The second principal is that most of those that want a non-ISO calendar system want it for user interaction, thus it is a UI localization issue. As such, date and time objects should be held as ISO objects in the data model and persistent storage, only being converted to and from a local calendar for display. The calendar system would be stored separately in the user preferences.
There are, however, some limited use cases where users believe they need to store and use dates in arbitrary calendar systems throughout the application. This is supported by {@link java.time.chrono.ChronoLocalDate}, however it is vital to read all the associated warnings in the Javadoc of that interface before using it. In summary, applications that require general interoperation between multiple calendar systems typically need to be written in a very different way to those only using the ISO calendar, thus most applications should just use ISO and avoid {@code ChronoLocalDate}.
Throughout all of this, a key goal was to allow date-time fields and units to be defined by applications. This has been achieved having tried many different designs.