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:

InstantInitExample.java
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.
InstantFromToEpochExample.java
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.
InstantGetExample.java
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:

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:

InstantAddSubstractExample.java
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:

You also can use method compareTo(...) for comparison:

InstantCompareExample.java
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

Following program will list down all ChronoField and ChronoUnit and indicate which one supported, and which one not:

InstantIsSupportedExample.java
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:

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.
InstantToXXXDateTimeExample.java
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