420

I am wondering if there is a way to get current milliseconds since 1-1-1970 (epoch) using the new LocalDate, LocalTime or LocalDateTime classes of Java 8.

The known way is below:

long currentMilliseconds = new Date().getTime();

or

long currentMilliseconds = System.currentTimeMillis();
Georgios Syngouroglou
  • 18,813
  • 9
  • 90
  • 92
  • 8
    What's wrong with `System.currentTimeMillis()`? – Dawood ibn Kareem May 29 '14 at 22:59
  • 39
    @DavidWallace He's trying to get the time of a Date, not the current time? – Anubian Noob May 29 '14 at 22:59
  • 2
    "... a way to get current milliseconds ..." – Dawood ibn Kareem May 29 '14 at 23:00
  • milliseconds counting from 1-1-1970. I was wandering if there is a method to get them using the new classes of Java 8 LocalDate, LocalTime and LocalDateTime, cause i didn't found one. – Georgios Syngouroglou May 29 '14 at 23:02
  • 1
    My understanding of the purpose for those classes is that it is a "human-focused" understanding of time, and `currentTimeMillis` would be irrelevant in that context. Think Calendar + Wall-clock with really good precision, and no concerns about time zones and locality. So there's no way to get back to "UTC Time" from a LocalTime – Gus May 29 '14 at 23:05
  • Similar Question: [*How to covert LocalDateTime to a Long?*](https://stackoverflow.com/q/73870816/642706) with [one good Answer](https://stackoverflow.com/a/73871279/642706). – Basil Bourque Sep 27 '22 at 22:31

14 Answers14

444

I'm not entirely sure what you mean by "current milliseconds" but I'll assume it's the number of milliseconds since the "epoch," namely midnight, January 1, 1970 UTC.

If you want to find the number of milliseconds since the epoch right now, then use System.currentTimeMillis() as Anubian Noob has pointed out. If so, there's no reason to use any of the new java.time APIs to do this.

However, maybe you already have a LocalDateTime or similar object from somewhere and you want to convert it to milliseconds since the epoch. It's not possible to do that directly, since the LocalDateTime family of objects has no notion of what time zone they're in. Thus time zone information needs to be supplied to find the time relative to the epoch, which is in UTC.

Suppose you have a LocalDateTime like this:

LocalDateTime ldt = LocalDateTime.of(2014, 5, 29, 18, 41, 16);

You need to apply the time zone information, giving a ZonedDateTime. I'm in the same time zone as Los Angeles, so I'd do something like this:

ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/Los_Angeles"));

Of course, this makes assumptions about the time zone. And there are edge cases that can occur, for example, if the local time happens to name a time near the Daylight Saving Time (Summer Time) transition. Let's set these aside, but you should be aware that these cases exist.

Anyway, if you can get a valid ZonedDateTime, you can convert this to the number of milliseconds since the epoch, like so:

long millis = zdt.toInstant().toEpochMilli();
Community
  • 1
  • 1
Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
  • 6
    Note that [ZonedDateTime](http://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html) already *has* the `getEpochSecond` method (via [ChronoZonedDateTime default](http://docs.oracle.com/javase/8/docs/api/java/time/chrono/ChronoZonedDateTime.html#toEpochSecond--)). No need for the `Instant`. – mabi May 30 '14 at 16:27
  • 26
    Sure, if all you need is seconds, not milliseconds. – Stuart Marks May 30 '14 at 17:23
  • 1
    Ah well, I was imprecise: `ZonedDateTime` also has `Instant`s `getNano` method, so wouldn't you be able to just replace `inst` with `zdt` in your example? – mabi May 30 '14 at 17:25
  • Argh. `ChronoZonedDateTime` has `toEpochSecond` not `getEpochSecond`. So yes I think this allows skipping the use of `Instant`. I'll test and update. – Stuart Marks May 30 '14 at 17:35
  • 26
    Avoid the maths on nanos by using zdt.get(ChronoField.MILLI_OF_SECOND). Avoid all the maths by using zdt.toInstant().toEpochMilli() – JodaStephen Jul 07 '14 at 09:46
  • 1
    @JodaStephen zdt.getLong instead of just get (which returns int) – adoalonso Oct 30 '18 at 07:06
  • `LocalDateTime.now().toInstant(OffsetDateTime.now().offset)` there is also another solution without using `Zone` – user924 Aug 31 '23 at 11:58
139

What I do so I don't specify a time zone is,

System.out.println("ldt " + LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
System.out.println("ctm " + System.currentTimeMillis());

gives

ldt 1424812121078 
ctm 1424812121281

As you can see the numbers are the same except for a small execution time.

Just in case you don't like System.currentTimeMillis, use Instant.now().toEpochMilli()

brian
  • 10,619
  • 4
  • 21
  • 79
  • 6
    No, Epoch is relative to UTC but you get the current time from your local zone. – Rafael Membrives Dec 14 '17 at 11:51
  • 3
    @ChristofferHammarström the amount of milliseconds that have passed since the epoch is a fact independent of timezone. It's the same amount of milliseconds, no matter what time of day you call it. The two results are different because brian's machine took 203 milliseconds to execute the second command. – Fletch May 28 '20 at 05:38
  • Is it ok to use UTC when the user maybe in a different timezone – GilbertS Jun 14 '20 at 10:30
  • 5
    @GilbertS you should probably never use this exact code, use the API as intended. Date-time should always be UTC when stored on a computer or transmitted to another user. It should usually be presented to the user as a local date time using their own time zone settings. – brian Jun 14 '20 at 14:41
  • As @Fletch has already mentioned, the result has nothing to do with the timezone. The reason behind the difference is that it took 203 milliseconds to execute the second command. You can replace `System.out.println("ctm " + System.currentTimeMillis());` with `System.out.println("ldt " + LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());` i.e. execute the exact same statement twice and you will still see the difference equal to the no. of milliseconds elapsed since the last execution of the same statement. – Arvind Kumar Avinash Jan 07 '21 at 20:32
26

Since Java 8 you can call java.time.Instant.toEpochMilli().

For example the call

final long currentTimeJava8 = Instant.now().toEpochMilli();

gives you the same results as

final long currentTimeJava1 = System.currentTimeMillis();
Marteng
  • 1,179
  • 13
  • 31
  • 3
    "gives you the same results as" ... but takes more CPU power and stresses the garbage collector a lot more. – VasiliNovikov Dec 05 '18 at 15:12
  • 7
    I'd like to see the above quantified (especially for normal usage - e.g. not for some performance critical real-time application...) – Brian Agnew Oct 22 '19 at 10:07
24

To avoid ZoneId you can do:

LocalDateTime date = LocalDateTime.of(1970, 1, 1, 0, 0);

System.out.println("Initial Epoch (TimeInMillis): " + date.toInstant(ZoneOffset.ofTotalSeconds(0)).toEpochMilli());

Getting 0 as value, that's right!

Dani
  • 4,001
  • 7
  • 36
  • 60
  • 13
    `ZoneOffset.ofTotalSeconds(0)` it is the same as `ZoneOffset.UTC` – Anton N Nov 09 '17 at 15:59
  • 1
    Yes, it was me upvoting @AntonNovopashin’s comment. Since you needed UTC, you’re fine (you might want to mention that in the answer). BTW `ZoneOffset` is a subclass of `ZoneId`, so I wouldn’t exactly say you have avoided it, but as long as you’re happy… – Ole V.V. Jun 30 '18 at 15:05
  • My first comment was a bit harsh, but wasn’t meant as offensive. You took offense. I am sorry. I have deleted it. Allow me to ask the other way around: what might be our reason for wanting to avoid `ZoneId`? – Ole V.V. Jul 02 '18 at 20:14
  • @OleV.V Is it ok to use UTC. Isn't only for people living in UTC timezone. – GilbertS Jun 14 '20 at 10:31
  • 1
    @GilbertS I don’t think anyone lives in UTC time zone. Using UTC for times that are used across time zones is recommended as a good practice. See for example [Java Best Practice for Date Manipulation/Storage for Geographically Diverse Users](https://stackoverflow.com/questions/40075780/java-best-practice-for-date-manipulation-storage-for-geographically-diverse-user). Or maybe I didn’t understand your question? – Ole V.V. Jun 14 '20 at 11:20
15

You can use java.sql.Timestamp also to get milliseconds.

LocalDateTime now = LocalDateTime.now();
long milliSeconds = Timestamp.valueOf(now).getTime();
System.out.println("MilliSeconds: "+milliSeconds);
Dharman
  • 30,962
  • 25
  • 85
  • 135
Nalam
  • 314
  • 3
  • 8
  • 1
    You are ignoring the crucial need for a time zone. I do not recommend doing it this way. Also the `Timestamp` class is long outdated and filled with design problems, so I’d rather avoid it, especially when we can use the classes from `java.time` like `LocalDateTime`. – Ole V.V. Jun 29 '18 at 11:10
  • @OleV.V. Just curious about the design problems of `Timestamp`, Can you share some article on that? It helps me to avoid using `Timestamp` from my code as well. Thanks! – Nalam Jul 02 '18 at 02:55
  • 2
    Just short, it’s implemented as a subclass of `Date` but often cannot be handled as a `Date`. Most of the methods inherited from `Date` and one constructor are deprecated. Its `toString` method uses the JVM’s time zone, which confuses many since the same `Timestamp` is printed differently on different computers ([example](https://stackoverflow.com/questions/42766674/java-convert-java-time-instant-to-java-sql-timestamp-without-zone-offset)). – Ole V.V. Jul 02 '18 at 03:36
  • This is perfect for unit testing. Just replace the now with `LocalDate.of(year, month, day)` – G_V Jul 17 '19 at 10:05
  • This should be the accepted answer to workaround the "always UTC" values. – LeYAUable Dec 25 '19 at 02:34
13

To get the current time in milliseconds (since the epoch), use System.currentTimeMillis().

Anubian Noob
  • 13,426
  • 6
  • 53
  • 75
12

You can try this:

long diff = LocalDateTime.now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli();
Md. Kamruzzaman
  • 1,895
  • 16
  • 26
  • Please add some explanation too. – Sabito stands with Ukraine Dec 15 '20 at 10:51
  • if you use `LocalDateTime` without local offset (always use UTC only) then it's better to just use `Instant` for REST, Websockets and other logic, and then you can pass that `Instant` to `ZonedDateTime` when you want to format date time for UI with local offset. In this case you don't use `LocalDateTime` at all – user924 Oct 23 '22 at 15:17
  • `LocalDateTime.now().toInstant(OffsetDateTime.now().offset)` is easier – user924 Aug 31 '23 at 11:57
7

Why didn't anyone mentioned the method LocalDateTime.toEpochSecond():

LocalDateTime localDateTime = ... // whatever e.g. LocalDateTime.now()
long time2epoch = localDateTime.toEpochSecond(ZoneOffset.UTC);

This seems way shorter that many suggested answers above...

maxxyme
  • 2,164
  • 5
  • 31
  • 48
  • this is what I was looking for. That accepted answer was giving me the willies. – Brill Pappin Apr 15 '20 at 12:51
  • Accept its only available in API 26 :{ – Brill Pappin Apr 15 '20 at 12:52
  • 6
    Because it gives only seconds. It's weird that there is no `toEpochMilli` method, taken into account the fact that you can specify even nanoseconds in LocalDateTime: there is a method `LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)`. – izogfif May 29 '20 at 14:06
  • if you just knew the difference between seconds and milliseconds... – user924 Oct 23 '22 at 14:46
  • the question was about milliseconds and the guy says that it is weird that nobody mentioned seconds :D – user924 Oct 24 '22 at 10:32
5

For LocalDateTime I do it this way:

LocalDateTime.of(2021,3,18,7,17,24,341000000)
    .toInstant(OffsetDateTime.now().getOffset())
    .toEpochMilli()
Marina DU
  • 81
  • 2
  • 3
5

There are some methods available that no one has mentioned here. But I don't see a reason why they should not work.

In case of LocalDate, you can use the toEpochDay() method. It returns the number of days since 01/01/1970. That number then can be easily converted to milliseconds:

long dateInMillis = TimeUnit.DAYS.toMillis(myLocalDate.toEpochDays());

Documentation can be found here.

In case of LocalDateTime, you can use the toEpochSecond() method. It returns the number of seconds since 01/01/1970. That number then can be converted to milliseconds, too:

long dateTimeInMillis = TimeUnit.SECONDS.toMillis(myLocalDateTime.toEpochSeconds());

Documentation for that is here.

BenjyTec
  • 1,719
  • 2
  • 12
  • 22
4

I think this is more simpler:

ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault());
Assert.assertEquals(System.currentTimeMillis(), zdt.toInstant().toEpochMilli());

get the millis like System.currentTimeMillis() (from UTC).

JianrongChen
  • 156
  • 1
  • 2
3

If you have a Java 8 Clock, then you can use clock.millis() (although it recommends you use clock.instant() to get a Java 8 Instant, as it's more accurate).

Why would you use a Java 8 clock? So in your DI framework you can create a Clock bean:

@Bean
public Clock getClock() {
    return Clock.systemUTC();
}

and then in your tests you can easily Mock it:

@MockBean private Clock clock;

or you can have a different bean:

@Bean
public Clock getClock() {
    return Clock.fixed(instant, zone);
}

which helps with tests that assert dates and times immeasurably.

JeeBee
  • 17,476
  • 5
  • 50
  • 60
3

Date and time as String to Long (millis):

String dateTimeString = "2020-12-12T14:34:18.000Z";

DateTimeFormatter formatter = DateTimeFormatter
                .ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH);

LocalDateTime localDateTime = LocalDateTime
        .parse(dateTimeString, formatter);

Long dateTimeMillis = localDateTime
        .atZone(ZoneId.systemDefault())
        .toInstant()
        .toEpochMilli();
ognjenkl
  • 1,407
  • 15
  • 11
2
  default LocalDateTime getDateFromLong(long timestamp) {
    try {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC);
    } catch (DateTimeException tdException) {
      //  throw new 
    }
}

default Long getLongFromDateTime(LocalDateTime dateTime) {
    return dateTime.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli();
}
Mohamed.Abdo
  • 2,054
  • 1
  • 19
  • 12