How can I create a Java 8 LocalDate from a long Epoch time in Milliseconds?

263,608

Solution 1

If you have the milliseconds since the Epoch and want to convert them to a local date using the current local timezone, you can use

LocalDate date =
    Instant.ofEpochMilli(longValue).atZone(ZoneId.systemDefault()).toLocalDate();

but keep in mind that even the system’s default time zone may change, thus the same long value may produce different result in subsequent runs, even on the same machine.

Further, keep in mind that LocalDate, unlike java.util.Date, really represents a date, not a date and time.

Otherwise, you may use a LocalDateTime:

LocalDateTime date =
    LocalDateTime.ofInstant(Instant.ofEpochMilli(longValue), ZoneId.systemDefault());

Solution 2

You can start with Instant.ofEpochMilli(long):

LocalDate date =
  Instant.ofEpochMilli(startDateLong)
  .atZone(ZoneId.systemDefault())
  .toLocalDate();

Solution 3

I think I have a better answer.

new Timestamp(longEpochTime).toLocalDateTime();

Solution 4

Timezones and stuff aside, a very simple alternative to new Date(startDateLong) could be LocalDate.ofEpochDay(startDateLong / 86400000L)

Solution 5

A simple version based on @Michael Piefel answer:

LocalDate myDate = LocalDate.ofEpochDay(Duration.ofMillis(epochMillis).toDays());
Share:
263,608

Related videos on Youtube

Vihung
Author by

Vihung

Basic b*tch Java Web Applications Developer - Spring Boot, AWS, Angular, Bootstrap. Mac and iPhone user. Highly opinionated about Design/User Experience/Usability.

Updated on March 11, 2022

Comments

  • Vihung
    Vihung about 2 years

    I have an external API that returns me dates as longs, represented as milliseconds since the beginning of the Epoch.

    With the old style Java API, I would simply construct a Date from it with

    Date myDate = new Date(startDateLong)
    

    What is the equivalent in Java 8's LocalDate/LocalDateTime classes?

    I am interested in converting the point in time represented by the long to a LocalDate in my current local timezone.

    • Jon Skeet
      Jon Skeet over 8 years
      Well you have to start by working out what time zone you care about. A "milliseconds since epoch" value gives you an instant in time... that could refer to different dates in different time zones. Bear in mind that java.util.Date was never really a date in the way that LocalDate is - it was an instant in time as well.
    • hotzst
      hotzst over 8 years
      Check this question: stackoverflow.com/questions/21242110/…, which covers the conversion of java.util.Date into LocalDate
    • kevinarpe
      kevinarpe about 7 years
      Note: This Q&A is also valuable for those trying to convert File.lastModified() (epoch millis) to LocalDate(Time).
    • Georgios Syngouroglou
      Georgios Syngouroglou over 3 years
    • Mark Rotteveel
      Mark Rotteveel over 3 years
      @GeorgeSiggouroglou That questions asks the opposite of this question, so it is not a duplicate.
    • Georgios Syngouroglou
      Georgios Syngouroglou over 3 years
      @MarkRotteveel you are correct, I hurried, I removed the vote to close.
  • Basil Bourque
    Basil Bourque over 8 years
    +1 for being explicit about time zone. If omitted, the JVM’s current default time zone is implicitly applied in determining the date. For any given moment the date varies around the world by time zone as a new day dawns earlier in the east.
  • Meno Hochschild
    Meno Hochschild over 8 years
    +1 from me for more detailed explanation. By the way, even a non-system zone can change (by tzupdater-tool or by jdk-change) and hence produce different results before and after.
  • Holger
    Holger over 8 years
    @Meno Hochschild: I wasn’t focusing on hardcoded timezones but rather comparing with timezones specified by the user, read from a configuration file or environment variables, where the programmer naturally assumes that the may change. Hardcoded timezones are indeed much like the system default; the programmer is tempted into thinking they were never changing…
  • BAERUS
    BAERUS almost 7 years
    I think you should at least explain what the 86400000L stands for.
  • Michael Piefel
    Michael Piefel almost 7 years
    I thought it was very easy to spot that it’s the number of milliseconds in a day.
  • BAERUS
    BAERUS almost 7 years
    For some it is, and I figured that only that would make sense, but without recalculation how many ms a day really has, I wouldn't be sure. Just speaking for myself, I don't know this number so well that I automatically know what it stands for.
  • Michael Piefel
    Michael Piefel almost 7 years
    Note also that the accepted answer really is the best answer, it just looks overwhelming. My simple hack just my be enough in many case. It’s a pity that java.time does not include DateTimeConstants as Joda did.
  • Vadzim
    Vadzim about 6 years
    java.util.concurrent.TimeUnit.MILLISECONDS.toDays(startDateL‌​ong)
  • Demigod
    Demigod almost 6 years
    Can I use LocalDateTime.ofEpochSecond() with, for example milliseconds / 1000 ?
  • Holger
    Holger almost 6 years
    @Demigod you can, when you think specifying a ZoneOffset is better than specifying a ZoneId (you can not use ZoneId.systemDefault() anymore, or at least not without converting it for a particular Instant, but when you have an Instant, why not use LocalDateTime.ofInstant…).
  • Demigod
    Demigod almost 6 years
    @holger, I have a long (millis). Why ZoneId.systemDefault() cannot be used?
  • Holger
    Holger almost 6 years
    @Demigod LocalDateTime.ofEpochSecond(…) requires an actual ZoneOffset, but ZoneId.systemDefault() returns a ZoneId. A ZoneId can map to different offsets, depending on the point of time you’re referring to. That’s what LocalDateTime.ofInstant does for you, converting the specified ZoneId according to the provided Instant.
  • Mihai Morcov
    Mihai Morcov over 5 years
    I came hoping to find a more readable solution than this, what a downgrade from the old java.util approach....
  • Holger
    Holger over 5 years
    @MihaiMorcov it’s exactly the problem of the “old java.util approach” that it didn’t handle the semantic difference between a local data-time and a long value representing an instant.
  • Stepan Yakovenko
    Stepan Yakovenko over 5 years
    new Timestamp(ts).toLocalDateTime().toLocalDate()
  • PlexQ
    PlexQ over 5 years
    Epoch is defined as UTC and should be therefore be timezone independent, so the ZoneId should always be UTC.
  • PlexQ
    PlexQ over 5 years
    I mean - if you don't mind importing javal.sql.Timestamp, which, given Java's monolithic nature I suppose is fine because it's just all part of the JVM... but feels a bit smelly, but I still like it better as it recognized epoch is fundamentally in UTC.
  • Holger
    Holger over 5 years
    @PlexQ The specified timezone is not relevant for the Epoch, which indeed is timezone independent, but for the semantics of the resulting LocalDate or LocalDateTime. You can specify any timezone you want, as long as it is consistent with the subsequent use of these result objects. Think of what happens when you deal with multiple objects created by different methods. The typical use cases for local date or datetimes incorporate the system default timezone, e.g. LocalDateTime.now()LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentT‌​imeMillis()), ZoneId.systemDefault())
  • fjjiaboming
    fjjiaboming about 5 years
    Some ZoneID miss nanosecond and millisecond.
  • Holger
    Holger about 5 years
    @fjjiaboming there are no nanoseconds in the epochmillis in the first place. For any other loss of precision, name an actual example.
  • Ole V.V.
    Ole V.V. over 4 years
    The Timestamp class is poorly designed and long outdated. Your code will use the JVM’s time zone setting, but since this setting can be changed by another part of your program or another program running in the same JVM, we cannot be quite sure what it is.
  • Ruslan
    Ruslan over 4 years
    It's always better to be explicit about which timezone is used. Using the old java.sql.Timestamp has the drawback of having the system timezone applied implicitly which usually causes confusion among developers.
  • Ketan R
    Ketan R over 4 years
    This does not really relate much to the asked question
  • M. Prokhorov
    M. Prokhorov over 4 years
    @KetanR, I disagree. The question is "how to obtain a LocalDate from epoch-millis", and I show how, using java.sql.Date for shorthand. This approach makes sense in code that's already dealing with JDBC in some capacity, and it works just fine. If you still not convinced, explain how is it not related to initial question.
  • Ketan R
    Ketan R over 4 years
    If you read the question, it says "external API that returns me dates as longs" and you are explaining how this conversion can be done if you are receiving long date from SQL. Your answer does explain a very specific case of the date conversion but its not really relevant to question that has been ask ed.Your explanation could be a valid answer to some other related quesiton though.
  • M. Prokhorov
    M. Prokhorov over 4 years
    @KetanR, if one receives long date from SQL, I'd advise to change his schema so he no longer receives dates in such form. However, if one receives dates as millis-timestamps from elsewhere (the external API), and immediately uses these dates to make JDBC queries, then java.sql.Date approach is among the shortest available, code-wise, and I'd say it's not all that useful to go though Instant with all the intermediate temporal objects when the end result is the same.
  • Ketan R
    Ketan R over 4 years
    As i have already said and is evident from your latest explanation, your answer is correct but not for the question at hand Question says: "I am interested in converting the point in time represented by the long to a LocalDate in my current local timezone. " your answer tells: "receive dates as millis-timestamps, and immediately use these dates to make JDBC queries". I dont understand what is not clear here ?
  • Pryftan
    Pryftan almost 4 years
    @MihaiMorcov Agreed. What a nightmare. I am converting some really old code and I wanted a simple way to use the long value of a file last mod date and I have to do all this? A real shame.
  • Holger
    Holger almost 4 years
    @Pryftan “to use the long value of a file last mod date” is a very unspecific task. Are you sure you actually need a LocalDate? Maybe whatever you actually want to do with the long value, can be done with the Instant created via Instant.ofEpochMilli(longValue) too.
  • Holger
    Holger about 2 years
    @PlexQ Java is not monolithic anymore. To use java.sql.Timestamp when using modules, you have to declare a dependency to the module java.sql, which will in turn introduce dependencies to java.xml and java.logging.
  • PlexQ
    PlexQ about 2 years
    @Holger True, though I haven't seen anyone building on anything above Java 11 in the wild yet.
  • Holger
    Holger about 2 years
    @PlexQ well, the modularization has been introduced in Java 9.