17.4 Working with Instants
The temporal classes LocalTime, LocalDate, LocalDateTime, and ZonedDateTime are suitable for representing human time in terms of year, month, day, hour, minute, second, and time zone. The Instant class can be used for representing computer time, specially timestamps that identify to a higher precision when an event occurred on the timeline. Instants are suitable for persistence purposes—for example, in a database.
An Instant represents a point on the timeline, measured with nanosecond precision from a starting point or origin which is defined to be at 1970-01-01T00:00:00Z—that is, January 1, 1970, at midnight—and is called the epoch. Instants before the epoch have negative values, whereas instants after the epoch have positive values. The Z represents the time zone designator for the zero UTC offset, which is the time zone offset for all instants in the UTC standard (p. 1072). The text representation of the epoch shown above is in the ISO standard format used by the toString() method of the Instant class.
An Instant is modeled with two values:
- A long value to represent the epoch-second
- An int value to represent the nano-of-second
The nano-of-second must be a value in the range [0, 999999999]. This representation is reflected in the methods provided for dealing with instants. The Instant class shares many of the method name prefixes and the common method names in Table 17.2, p. 1026, and Table 17.3, p. 1026, with the other temporal classes, respectively. Although the Instant class has many methods analogous to the other temporal classes, as we shall see, there are also differences. Instant objects are, like objects of the other temporal classes, immutable and thread-safe.
Creating Instants
The Instant class provides the following predefined instants:
static Instant EPOCH
static Instant MAX
static Instant MIN
These static fields of the Instant class define constants for the epoch (1970-01-01T00:00:00Z), the maximum (1000000000-12-31T23:59:59.999999999Z), and the minimum instants (-1000000000-01-01T00:00Z), respectively.
Following are selected methods for creating and converting instances of the Instant class:
static Instant now()
Returns the current instant based on the system clock.
static Instant ofEpochMilli(long epochMilli)
static Instant ofEpochSecond(long epochSecond)
static Instant ofEpochSecond(long epochSecond, long nanoAdjustment)
These static factory methods return an Instant based on the millisecond, second, and nanosecond specified.
Nanoseconds are implicitly set to zero. The argument values can be negative. Note that the amount is specified as a long value.
String toString()
Returns a text representation of this Instant, such as “2021-01-11T14:18:30Z”. Formatting is based on the ISO instant format for date-time:
uuuu-MM-ddTHH:mm:ss.SSSSSSSSSZ
where Z designates the UTC standard (also known as Coordinated Universal Time).
static Instant parse(CharSequence text)
Returns an Instant parsed from a character sequence, such as “2021-04-28T14:18:30Z”, based on the ISO instant format. A DateTimeParse-Exception is thrown if the text cannot be parsed to an instant.
ZonedDateTime atZone(ZoneId zone)
Returns a ZonedDateTime by combining this instant with the specified time zone (p. 1072).
Analogous to the other temporal classes, the Instant class also provides the now() method to obtain the current instant from the system clock.
Instant currentInstant = Instant.now(); // 2021-03-09T10:48:01.914826Z
The Instant class provides the static factory method ofEpochUNIT() to construct instants from seconds and nanoseconds. There is no method to construct an instant from just nanoseconds.
Instant inst1 = Instant.ofEpochMilli(-24L*60*60*1000);// Date 1 day before epoch.
Instant inst2 = Instant.ofEpochSecond(24L*60*60); // Date 1 day after epoch.
Instant inst3 = Instant.ofEpochSecond(24L*60*60 – 1, // Date 1 day after epoch.
1_000_000_000L);
out.println(“A day before: ” + inst1); // Date 1 day before: 1969-12-31T00:00:00Z
out.println(“A day after: ” + inst2); // Date 1 day after : 1970-01-02T00:00:00Z
out.println(“A day after: ” + inst3); // Date 1 day after : 1970-01-02T00:00:00Z
Note that the amount specified is a long value. The last statement above also illustrates that the nanosecond is adjusted so that it is always between 0 and 999,999,999. The adjustment results in the nanosecond being set to 0 and the second being incremented by 1.
The toString() method of the Instant class returns a text representation of an Instant based on the ISO standard. The code shows the text representation of the instant 500 nanoseconds after the epoch.
Instant inst4 = Instant.ofEpochSecond(0, 500);
out.println(“Default format: ” + inst4); // 1970-01-01T00:00:00.000000500Z
The Instant class also provides the parse() static method to create an instant from a string that contains a text representation of an instant, based on the ISO standard. Apart from treating the value of the nanosecond as optional, the method is strict in parsing the string. If the format of the string is not correct, a DateTimeParseException is thrown.
Instant instA = Instant.parse(“1970-01-01T00:00:00.000000500Z”);
Instant instB = Instant.parse(“1949-03-01T12:30:15Z”);
Instant instC = Instant.parse(“-1949-03-01T12:30:15Z”);
Instant instD = Instant.parse(“-1949-03-01T12:30:15”); // DateTimeParseException!
The code below illustrates creating an Instant by combining a LocalDateTime object with a time zone offset. Three different zone-time offsets are specified at (2), (3), and (4) to convert the date-time created at (1) to an Instant on the UTC timeline, which has offset zero. Note that an offset ahead of UTC is subtracted and an offset behind UTC is added to adjust the values of the date/time from the LocalDateTime object to the UTC timeline.
LocalDateTime ldt = LocalDate.of(2021, 12, 25).atStartOfDay(); //(1)
Instant i1 = ldt.toInstant(ZoneOffset.of(“+02:00”)); // (2) Ahead of UTC
Instant i2 = ldt.toInstant(ZoneOffset.UTC); // (3) At UTC
Instant i3 = ldt.toInstant(ZoneOffset.of(“-02:00”)); // (4) Behind UTC
System.out.println(“ldt: ” + ldt);
System.out.println(“i1: ” + i1);
System.out.println(“i2: ” + i2);
System.out.println(“i3: ” + i3);
Output from the code:
ldt: 2021-12-25T00:00
i1: 2021-12-24T22:00:00Z
i2: 2021-12-25T00:00:00Z
i3: 2021-12-25T02:00:00Z
// LocalDateTime
default Instant toInstant(ZoneOffset offset)
Converts a date-time to an instant by combining this LocalDateTime object with the specified time zone. The valid offset in Java is in the range from –18 to +18 hours. The absolute value of the offset is added to or subtracted from the date-time depending on whether it is specified as a negative or positive value, respectively, keeping in mind that an Instant represents a point in time on the UTC timeline.
This method is inherited by the LocalDateTime class from its superinterface java.time.chrono.ChronoLocalDateTime.