JSR-310 Date and Time API Guide
NOTE: The Java Time API defined by JSR 310 is provided as part of JDK-8. The specification is the Javadocs for the java.time packages. This guide introduces the API for the purpose of review.
Many Java applications require logic to store and manipulate dates and times. At present, Java SE provides a number of disparate APIs for this purpose, including Date, Calendar, SQL Date/Time/Timestamp and XML Duration/XMLGregorianCalendar. JSR improves on these APIs and covers many additional use cases needed by developers.
As an example, Java developers currently have no standard Java SE class to represent the concept of a date without a time, a time without a date or a duration. The result of these missing features has been widespread abuse of the facilities which are provided, such as using the Date or Calendar class with the time set to midnight to represent a date without a time. Such an approach is very error-prone - there are certain time zones where midnight does not exist once a year due to the daylight saving time cutover!
JSR-310 tackles this by providing a comprehensive set of date and time classes suitable for Java SE today. The API includes:
This document is an introduction to the full API, which consists of the Javadoc. The Javadoc specification is available via the JCP JSR 310 Date and Time API . The early access reference implementation included in JDK 8 is available for download. Additional information related to JSR 310 can be found at the Threeten Project on GitHub.
This draft guide is released to gain feedback. Since it is a draft, readers are advised to take care when referencing it.
2. Date and Time terminology
The domain of dates, times and other temporal concepts is large and complex - much more complex than is often apparent. A key aim of the JSR is to allow the API to explain this complexity simply by the way that the features are exposed. In this way, the user of the API is guided to make the correct choice, minimising the potential for bugs.
Part of this process is determining and using a consistent terminology. For this purpose, JSR-310 is building upon the excellent work of the ISO-8601 standard. However, we have changed a few terms, thus the entire terminology is defined here for clarity:
3. Design Goals
The JSR-310 classes should be immutable wherever possible. Experience over time has shown that APIs at this level should consist of simple immutable objects. These are simple to use, can be easily shared, are inherently thread-safe, friendly to the garbage collector and tend to have fewer bugs due to the limited state-space.
The API strives to be fluent within the standard patterns of Java SE. A fluent API has methods that are easy to read and understand, specifically when chained together. The key goal here is to simplify the use and enhance the readability of the API.
Clear, explicit and expected
Each method in the API should be well-defined and clear in what it does. This is not just a question of good Javadoc, but also of ensuring that the method can be called in isolation successfully and meaningfully.
The API should be extensible in well defined ways by application developers, not just JSR authors. The reasoning is simple - there are just far too many weird and wonderful ways to manipulate time. A JSR cannot capture all of them, but an extensible JSR design can allow for them to be added as required by application developers or open source projects.
4. Machine and Human
We classify dates and times into two basic use cases - machine-scale and human-scale.
4.1 Machine-scale time
Machine-scale time represents the passage of time using a single, continually incrementing number. The rules that determine how the scale is measured and communicated are typically defined by international scientific standards organizations.
Two key classes are defined to represent machine-scale time:
These classes use nanosecond precision. The classes have sufficient accuracy to represent any nanosecond instant within the current age of the universe. The epoch used is 1970-01-01T00:00:00Z (midnight at the start of 1 January 1970 UTC), as per the current Java SE date and time classes.
4.2 Human-scale time
Human-scale time represents the passage of time using a number of named fields, such as year, month, day, hour, minute and second. The rules that determine how the fields work together are defined in a calendar system.
The design adopted splits the classes into value types and fields/units. Simple applications will not need to be concerned with fields and units.
4.2.1 Value types
The high level API contains the following key classes:
Each of these date-time classes represent time in the ISO calendar system, defined by ISO-8601. This is also known as the proleptic Gregorian calendar system, and is the de facto civil calendar system used today in the vast majority of the world.
Each date-time field can be represented as a value, which is expressed as a long. Some fields also have an enum defined for code clarity and safety. These include month, day of week, am/pm and quarter.
Although there are lots of classes and each class has lots of methods, the "conceptual weight" of the API is greatly reduced through consistent use of method name prefixes. Some of these prefixes differ from JavaBean conventions because the classes are immutable:
Applications will also commonly use the TemporalAdjuster interface and the standard implementations provided in TemporalAdjusters. These pre-packaged common manipulation functions like “next Wednesday” or the “last day of the month”. They are especially valuable in capturing the intent of business logic.
4.2.2 Fields and units
Dates and times are formed from fields and units.
A unit is a measurable unit of time, such as a year, month or hour. The set of known units can be extended by applications.
A field is used to express part of a larger date-time, such as year, month-of-year or second-of-minute. The set of known fields can also be extended by applications.
Fields and units work together with the abstractions Temporal and TemporalAccessor provide access to date-time classes in a generic manner.
Other calendar systems are supported with a separate calendar-neutral API. This is focused on the Chronology and ChronoLocalDate classes. These do not have the same breadth or depth as the main ISO calendar system API.
It is recommended that applications use the classes in the main API for all communication between systems and subsystems, including public APIs, storage to a database and communication across the network. The calendar neutral API should be used primarily for user localization.
4.3 Machine/Human comparison
The division in the API between machine-scale and human-scale is deliberate and necessary, as the two time-scales represent different ways of looking at time.
The machine-scale approach is very time-line focused. For example, Instant simply represents an instant on the time-line. The only meaningful operations on the class are to check whether the instant is before or after another instant. These classes will be of most use for recording event timestamps and logging.
The human-scale approach is very focused on what the time means to a human, through the use of the fields. In addition to getting and setting the field values, methods are provided to perform mathematical operations, such as adding three days to a date. These classes will be of most use in business logic, such as representing the departure time of a train or a customer's birthday.
4.4 Calendar/Joda-Time comparison
The design adopted is notably different to the Java SE Calendar API and the Joda-Time API.
The Java SE Calendar API has a single base class that represents both the date-time and the calendar system. Different calendar systems are implemented as subclasses. This design is flawed as calendar systems are too different to be properly treated as subclasses.
The Joda-Time API has simple date-time classes with a plug-in calendar system (chronology). This design, while better than Calendar, is also flawed because each method on the API is unable to properly define its result. For example, the getMonthOfYear() method normally returns a value from 1 to 12, however if the Coptic calendar system has been "plugged in" then the method will return results from 1 to 13.
The JSR-310 design ensures that each method on the core API is able to fully define its input and output by focusing the entire class on a single calendar system. Instead, users with advanced requirements have to study the API a little more closely and use the low-level temporal classes.
The ThreeTen project and JSR-310 needs feedback! We need reviewers to read the guide and Javadoc, and where possible, try out the code (in the JDK 8 Early Access Releases).
Specifically, we need to know if
Feedback and comments on the specification review drafts should be sent to firstname.lastname@example.org.
Feedback is public information on a trust and respect basis for the public good and may be used by anyone in any way forever.