Java Instant Tutorial with Examples
Java Instant class is used to represent a specific moment on the time line. This might be used to record event time-stamps in the application. This class is immutable and thread-safe.
Unlike the old java.util.Date which has milliseconds precision, an Instant has nanoseconds precision. Representing a point in time using nanoseconds precision requires the storage of a number larger than a long. To achieve this, the class stores a long representing epoch-seconds and an int representing nanosecond-of-second, which will always be between 0 and 999,999,999. The epoch-seconds are measured from the standard Java epoch of 1970-01-01T00:00:00Z where instants after the epoch have positive values, and earlier instants have negative values
Creating an Instant
You create an Instant instance using one of the Instant class factory methods:
- static Instant now(): Obtains the current instant from the system clock.
- static Instant now(Clock clock): Obtains the current instant from the specified clock.
- static Instant ofEpochMilli(long epochMilli): Obtains an instance of Instant using milliseconds from the epoch of 1970-01-01T00:00:00Z.
- static Instant ofEpochSecond(long epochSecond): Obtains an instance of Instant using seconds from the epoch of 1970-01-01T00:00:00Z.
- static Instant ofEpochSecond(long epochSecond, long nanoAdjustment): Obtains an instance of Instant using seconds from the epoch of 1970-01-01T00:00:00Z and nanosecond fraction of second.
- static Instant parse(CharSequence text): Obtains an instance of Instant from a text string such as 2007-12-03T10:15:30.00Z.
import java.time.Clock;
import java.time.Instant;
public class InstantInitExample {
public static void main(String[] args) {
Instant instant1 = Instant.now();
System.out.println("Instant1: " + instant1);
Instant instant2 = Instant.now(Clock.systemUTC());
System.out.println("Instant2: " + instant2);
long now = System.currentTimeMillis();
Instant instant3 = Instant.ofEpochMilli(now);
System.out.println("Instant3: " + instant3);
now = now/1000;
Instant instant4 = Instant.ofEpochSecond(now);
System.out.println("Instant4: " + instant4);
Instant instant5 = Instant.ofEpochSecond(now, 345000000);
System.out.println("Instant5: " + instant5);
Instant instant6 = Instant.parse("1980-04-09T10:15:30.00Z");
System.out.println("Instant6: " + instant6);
}
}
Instant1: 2019-08-18T14:38:40.108Z Instant2: 2019-08-18T14:38:40.180Z Instant3: 2019-08-18T14:38:40.180Z Instant4: 2019-08-18T14:38:40Z Instant5: 2019-08-18T14:38:40.345Z Instant6: 1980-04-09T10:15:30Z
There is method toInstant() in java.util.Date to convert Date object to an Instant.
long now = System.currentTimeMillis();
Date date = new Date(now);
Instant instant = date.toInstant();
System.out.println("instant: " + instant);
instant: 2019-08-18T14:56:06.157Z
Instant from and to Epoch
Using Instant.ofEpochMilli(...) we can obtain an instance of Instant using milliseconds from the epoch. The other way, we can convert an Instant to the number of milliseconds from the epoch:
- long toEpochMilli(): Converts this instant to the number of milliseconds from the epoch of 1970-01-01T00:00:00Z.
import java.time.Instant;
public class InstantFromToEpochExample {
public static void main(String[] args) {
Instant instant = Instant.parse("1980-04-09T15:30:45.123Z");
System.out.println("Instant : " + instant);
System.out.println("Instant.toEpochMilli(): " + instant.toEpochMilli());
Instant copyInstant = Instant.ofEpochMilli(instant.toEpochMilli());
System.out.println("Copied Instant : " + copyInstant);
}
}
Instant : 1980-04-09T15:30:45.123Z Instant.toEpochMilli(): 324142245123 Copied Instant : 1980-04-09T15:30:45.123Z
Accessing Specified Field of an Instant
An Instant object contains two fields internally which holds the time represented by the Instant:
- Seconds since the epoch.
- Nanoseconds - part of the instant which is less than one second
We can access both the seconds and nanoseconds via these methods:
- long getEpochSecond(): Gets the number of seconds from the Java epoch of 1970-01-01T00:00:00Z.
- int getNano(): Gets the number of nanoseconds, later along the time-line, from the start of the second.
import java.time.Instant;
public class InstantGetExample {
public static void main(String[] args) {
Instant instant = Instant.now();
System.out.println("Instant : " + instant);
long epochSecond = instant.getEpochSecond();
System.out.println("EpochSecond: " + epochSecond);
int nano = instant.getNano();
System.out.println("Nano : " + nano);
}
}
Instant : 2019-08-18T17:19:28.115Z EpochSecond: 1566148768 Nano : 115000000
Method get(...) and getLong(...) also exists to get the value of specified field from an Instant:
- int get(TemporalField field): Gets the value of the specified field from this instant as an int.
- long getLong(TemporalField field): Gets the value of the specified field from this instant as a long.
long epochSecond = instant.getLong(ChronoField.INSTANT_SECONDS);
System.out.println("EpochSecond: " + epochSecond);
int nano = instant.get(ChronoField.NANO_OF_SECOND);
System.out.println("Nano : " + nano);
EpochSecond: 1566148768 Nano : 115000000
As you can see from example above, getLong(ChronoField.INSTANT_SECONDS) is equal to getEpochSecond() and get(ChronoField.NANO_OF_SECOND) is equal to getNano().
Note: Not all fields are supported. If you try to get one of unsupported field, you will get following error: java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfWeek
Add/Subtract Operations on Instant
The Instant class also has several methods which can be used to do add/subtract operations:
- Instant minus(long amountToSubtract, TemporalUnit unit): Returns a copy of this instant with the specified amount subtracted.
- Instant minus(TemporalAmount amountToSubtract): Returns a copy of this instant with the specified amount subtracted.
- Instant minusMillis(long millisToSubtract): Returns a copy of this instant with the specified duration in milliseconds subtracted.
- Instant minusNanos(long nanosToSubtract): Returns a copy of this instant with the specified duration in nanoseconds subtracted.
- Instant minusSeconds(long secondsToSubtract): Returns a copy of this instant with the specified duration in seconds subtracted.
- Instant plus(long amountToAdd, TemporalUnit unit): Returns a copy of this instant with the specified amount added.
- Instant plus(TemporalAmount amountToAdd): Returns a copy of this instant with the specified amount added.
- Instant plusMillis(long millisToAdd): Returns a copy of this instant with the specified duration in milliseconds added.
- Instant plusNanos(long nanosToAdd): Returns a copy of this instant with the specified duration in nanoseconds added.
- Instant plusSeconds(long secondsToAdd): Returns a copy of this instant with the specified duration in seconds added.
import java.time.Duration;
import java.time.Instant;
import java.time.Period;
import java.time.temporal.ChronoUnit;
public class InstantAddSubstractExample {
public static void main(String[] args) {
Instant instant = Instant.parse("1984-08-13T10:15:30.345Z");
System.out.println("Instant : " + instant);
// Adding/subtracting seconds
System.out.println("15 seconds before : " + instant.minusSeconds(15));
System.out.println("10 seconds after : " + instant.plusSeconds(10));
// Adding/subtracting millis
System.out.println("Minus 45000 millis : " + instant.minusMillis(45000));
System.out.println("Plus 10000 millis : " + instant.plusMillis(10000));
// Adding/subtracting nanos
System.out.println("Minus 45123456 nanos: " + instant.minusNanos(45123456));
System.out.println("Plus 111234567 nanos: " + instant.plusNanos(111234567));
// Using MINUTES
System.out.println("45 minutes before : " + instant.minus(45, ChronoUnit.MINUTES));
// Using HOURS
System.out.println("3 hours before : " + instant.minus(3, ChronoUnit.HOURS));
// Using MILLIS also supported
System.out.println("30000 millis later : " + instant.plus(30000, ChronoUnit.MILLIS));
// Using DAYS
System.out.println("10 days later : " + instant.plus(10, ChronoUnit.DAYS));
// Using TemporalAmount - Duration
System.out.println("10 seconds before : " + instant.minus(Duration.ofSeconds(10)));
// Using TemporalAmount - Period
System.out.println("5 days later : " + instant.plus(Period.ofDays(5)));
}
}
Instant : 1984-08-13T10:15:30.345Z 15 seconds before : 1984-08-13T10:15:15.345Z 10 seconds after : 1984-08-13T10:15:40.345Z Minus 45000 millis : 1984-08-13T10:14:45.345Z Plus 10000 millis : 1984-08-13T10:15:40.345Z Minus 45123456 nanos: 1984-08-13T10:15:30.299876544Z Plus 111234567 nanos: 1984-08-13T10:15:30.456234567Z 45 minutes before : 1984-08-13T09:30:30.345Z 3 hours before : 1984-08-13T07:15:30.345Z 30000 millis later : 1984-08-13T10:16:00.345Z 10 days later : 1984-08-23T10:15:30.345Z 10 seconds before : 1984-08-13T10:15:20.345Z 5 days later : 1984-08-18T10:15:30.345Z
Note: Not all units are supported. If you try to get one of unsupported unit, you will get following error: java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Months
Comparing Two Instants
Methods isAfter() and isBefore() used to compare two Instants:
- boolean isAfter(Instant otherInstant): Checks if this instant is after the specified instant.
- boolean isBefore(Instant otherInstant): Checks if this instant is before the specified instant.
You also can use method compareTo(...) for comparison:
- int compareTo(Instant otherInstant): Compares this instant to the specified instant.
import java.time.Instant;
public class InstantCompareExample {
public static void main(String[] args) {
Instant instant1 = Instant.parse("1997-05-07T15:20:45.765Z");
Instant instant2 = Instant.parse("1997-05-07T15:20:45.785Z");
System.out.println("Instant1 : " + instant1);
System.out.println("Instant2 : " + instant2);
System.out.println("Instant1 after Instant2 : " + instant1.isAfter(instant2));
System.out.println("Instant1 before Instant2 : " + instant1.isBefore(instant2));
System.out.println("Instant1 compareTo Instant2: " + instant1.compareTo(instant2));
System.out.println("Instant2 compareTo Instant1: " + instant2.compareTo(instant1));
}
}
Instant1 : 1997-05-07T15:20:45.765Z Instant2 : 1997-05-07T15:20:45.785Z Instant1 after Instant2 : false Instant1 before Instant2 : true Instant1 compareTo Instant2: -20000000 Instant2 compareTo Instant1: 20000000
Supported Field and Unit of an Instant
Methods isSupported(...) can be used to check if a particular field/unit is supported in an Instant
- boolean isSupported(TemporalField field): Checks if the specified field is supported.
- boolean isSupported(TemporalUnit unit): Checks if the specified unit is supported.
Following program will list down all ChronoField and ChronoUnit and indicate which one supported, and which one not:
import java.time.Instant;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
public class InstantIsSupportedExample {
public static void main(String[] args) {
Instant instant = Instant.now();
System.out.println("*** ChronoField ***");
for(ChronoField chronoField : ChronoField.values()){
System.out.println(chronoField + " is supported:" + instant.isSupported(chronoField));
}
System.out.println("\n*** ChronoUnit ***");
for(ChronoUnit chronoUnit : ChronoUnit.values()){
System.out.println(chronoUnit + " is supported:" + instant.isSupported(chronoUnit));
}
}
}
*** ChronoField *** NanoOfSecond is supported:true NanoOfDay is supported:false MicroOfSecond is supported:true MicroOfDay is supported:false MilliOfSecond is supported:true MilliOfDay is supported:false SecondOfMinute is supported:false SecondOfDay is supported:false MinuteOfHour is supported:false MinuteOfDay is supported:false HourOfAmPm is supported:false ClockHourOfAmPm is supported:false HourOfDay is supported:false ClockHourOfDay is supported:false AmPmOfDay is supported:false DayOfWeek is supported:false AlignedDayOfWeekInMonth is supported:false AlignedDayOfWeekInYear is supported:false DayOfMonth is supported:false DayOfYear is supported:false EpochDay is supported:false AlignedWeekOfMonth is supported:false AlignedWeekOfYear is supported:false MonthOfYear is supported:false ProlepticMonth is supported:false YearOfEra is supported:false Year is supported:false Era is supported:false InstantSeconds is supported:true OffsetSeconds is supported:false *** ChronoUnit *** Nanos is supported:true Micros is supported:true Millis is supported:true Seconds is supported:true Minutes is supported:true Hours is supported:true HalfDays is supported:true Days is supported:true Weeks is supported:false Months is supported:false Years is supported:false Decades is supported:false Centuries is supported:false Millennia is supported:false Eras is supported:false Forever is supported:false
Getting LocalDateTime or OffsetDateTime or ZonedDateTime
Instant does not support human units of time like months/years. Such handling requires converting Instant to LocalDateTime, OffsetDateTime, or ZonedDateTime.
Following method is used to create OffsetDateTime from an Instant:
- OffsetDateTime atOffset(ZoneOffset offset): Combines this instant with an offset to create an OffsetDateTime.
And this method is to create ZonedDateTime from an Instant:
- ZonedDateTime atZone(ZoneId zone): Combines this instant with a time-zone to create a ZonedDateTime.
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class InstantToXXXDateTimeExample {
public static void main(String[] args) {
Instant instant = Instant.parse("1997-05-07T10:15:30.00Z");
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println("LocalDateTime : " + localDateTime);
ZonedDateTime zonedDateTime1 = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println("ZonedDateTime1: " + zonedDateTime1);
ZonedDateTime zonedDateTime2 = instant.atZone(ZoneId.of("Asia/Tokyo"));
System.out.println("ZonedDateTime2: " + zonedDateTime2);
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.UTC);
System.out.println("OffsetDateTime: " + offsetDateTime);
}
}
LocalDateTime : 1997-05-07T18:15:30 ZonedDateTime1: 1997-05-07T18:15:30+08:00[Asia/Singapore] ZonedDateTime2: 1997-05-07T19:15:30+09:00[Asia/Tokyo] OffsetDateTime: 1997-05-07T10:15:30Z