How to convert from Instant to LocalDate
Java 8Localdatejava.time.instantJava TimeJava 8 Problem Overview
I have an Instant
coming from a source that should, according to the specs, be a LocalDate
, but don't see any methods in the LocalDate
class to convert the Instant
to a LocalDate
.
What is the best way to do this?
Java 8 Solutions
Solution 1 - Java 8
Java 9+
LocalDate.ofInstant(...)
arrived in Java 9.
Instant instant = Instant.parse("2020-01-23T00:00:00Z");
ZoneId zone = ZoneId.of("America/Edmonton");
LocalDate date = LocalDate.ofInstant(instant, zone);
See code run live at IdeOne.com.
Notice the date is 22nd rather than 23rd as that time zone uses an offset several hours before UTC.
> 2020-01-22
Java 8
If you are using Java 8, then you could use ZonedDateTime
's toLocalDate()
method:
yourInstant.atZone(yourZoneId).toLocalDate()
Solution 2 - Java 8
Other answers provided the mechanics for the transformation, but I wanted to add some background on the meaning of such transformation which hopefully helps explain why it works the way it works.
LocalDate
and Instant
seem similar – they both hold date(/time) information without the time zone information. However, they have quite a different meaning.
Instant
represents a point in time unambiguously. The representation does not explicitly contain any time zone, but implicitly it refers to the UTC time line.
LocalDateTime
(and LocalDate
) is ambiguous, because it represents a point in the local timeline, which implicitly refers to the local time zone.
So, in order to correctly transform an Instant
into a LocalDateTime
(conceptually – some of these steps are bundled together into a single operation in the implementation) you need to:
- convert the
Instant
into aZonedDateTime
by applying the UTC time zone info - change the time zone from UTC to the local time zone (which implies applying the relevant time zone offset) which gives you another
ZonedDateTime
(with different time zone) - convert the
ZonedDateTime
into aLocalDateTime
which makes the time zone implicit (local) by removing the time zone info.
Finally, you can drop the time-part of LocalDateTime
and end up with the LocalDate
.
Solution 3 - Java 8
If using java 8 you can do the following
Instant instantOfNow = Instant.now();
LocalDate localDate
= LocalDateTime.ofInstant(instantOfNow, ZoneOffset.UTC).toLocalDate();
Solution 4 - Java 8
You need to ask yourself at what zone offset you want to transform it to most probably and when you know the answer to that:
LocalDate.ofInstant(yourInstant, yourZoneOffSet)
EDIT
just realized that this is only possible since java-9, for a pre-java9 see the other answer
Solution 5 - Java 8
Complete running example, Java 8 compatible:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
class Scratch {
public static void main(String[] args) {
Instant now = Instant.now();
LocalDateTime ldt = now.atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(ldt);
}
}
Solution 6 - Java 8
Instant instant = Instant.now();
LocalDate localDate = LocalDate.ofInstant(instant, ZoneOffset.UTC);
the above code worked for me.