443

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(); 
6
  • 8
    What's wrong with System.currentTimeMillis()? Commented May 29, 2014 at 22:59
  • 44
    @DavidWallace He's trying to get the time of a Date, not the current time? Commented May 29, 2014 at 22:59
  • 2
    "... a way to get current milliseconds ..." Commented May 29, 2014 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. Commented May 29, 2014 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 Commented May 29, 2014 at 23:05

16 Answers 16

468

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(); 
Sign up to request clarification or add additional context in comments.

7 Comments

Note that ZonedDateTime already has the getEpochSecond method (via ChronoZonedDateTime default). No need for the Instant.
Sure, if all you need is seconds, not milliseconds.
Ah well, I was imprecise: ZonedDateTime also has Instants getNano method, so wouldn't you be able to just replace inst with zdt in your example?
Avoid the maths on nanos by using zdt.get(ChronoField.MILLI_OF_SECOND). Avoid all the maths by using zdt.toInstant().toEpochMilli()
@JodaStephen zdt.getLong instead of just get (which returns int)
|
152

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()

5 Comments

No, Epoch is relative to UTC but you get the current time from your local zone.
@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.
Is it ok to use UTC when the user maybe in a different timezone
@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.
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.
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(); 

2 Comments

"gives you the same results as" ... but takes more CPU power and stresses the garbage collector a lot more.
I'd like to see the above quantified (especially for normal usage - e.g. not for some performance critical real-time application...)
23

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!

5 Comments

ZoneOffset.ofTotalSeconds(0) it is the same as ZoneOffset.UTC
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…
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?
@OleV.V Is it ok to use UTC. Isn't only for people living in UTC timezone.
@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. Or maybe I didn’t understand your question?
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); 

5 Comments

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.
@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!
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).
This is perfect for unit testing. Just replace the now with LocalDate.of(year, month, day)
This should be the accepted answer to workaround the "always UTC" values.
14

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

Comments

14

You can try this:

long diff = LocalDateTime.now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli(); 

3 Comments

Please add some explanation too.
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
LocalDateTime.now().toInstant(OffsetDateTime.now().offset) is easier
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...

5 Comments

this is what I was looking for. That accepted answer was giving me the willies.
Accept its only available in API 26 :{
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).
if you just knew the difference between seconds and milliseconds...
the question was about milliseconds and the guy says that it is weird that nobody mentioned seconds :D
6

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).

Comments

6

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.toEpochDay()); 

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.toEpochSecond()); 

2 Comments

The correct method is: toEpochDay
Thanks for pointing this out, fixed the typo.
5

For LocalDateTime I do it this way:

LocalDateTime.of(2021,3,18,7,17,24,341000000) .toInstant(OffsetDateTime.now().getOffset()) .toEpochMilli() 

Comments

4

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.

Comments

4

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(); 

Comments

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(); } 

Comments

0

My simple code for resolve parsing ISO date format with offset and without them.

In second part (in else condition) - the way How I solved the problem with parsing time of era and time of day into Milliseconds.

 public static long parseISO8601WithCurrentOffset(String iso8601String) { TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse(iso8601String); if (temporalAccessor.isSupported(ChronoField.OFFSET_SECONDS)) { // 2024-07-01T15:30:45.102+03:00 long inputTime = Instant.from(temporalAccessor).toEpochMilli(); long inputOffset = TimeUnit.SECONDS.toMillis(temporalAccessor.getLong(ChronoField.OFFSET_SECONDS)); long finalTime = inputTime - inputOffset; return finalTime + TimeUnit.SECONDS.toMillis(TimeFieldUtils.getServerOffset().getTotalSeconds()); } else { // 2024-07-01T15:30:45.102 // 23:59:59.102_000000 LocalTime timeOfDay = temporalAccessor.query(TemporalQueries.localTime()); // 01.07.2024 LocalDate timeOfEra = temporalAccessor.query(TemporalQueries.localDate()); long msOfDay = timeOfDay.getLong(ChronoField.MILLI_OF_DAY); long msOfEra = TimeUnit.DAYS.toMillis(LocalDate.EPOCH.until(timeOfEra, ChronoUnit.DAYS)); return msOfEra + msOfDay; } } 

It also can be used as a creating and returing date :\ But in this case - use a Calendar, it more easely to understand.

 LocalTime timeOfDay = LocalTime.of(10, 10, 10); LocalDate timeOfEra = LocalDate.of(2025, 10, 2); return TimeUnit.DAYS.toMillis(LocalDate.EPOCH.until(timeOfEra, ChronoUnit.DAYS)) + timeOfDay.getLong(ChronoField.MILLI_OF_DAY); 
 Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.ZONE_OFFSET, (int) TimeUnit.SECONDS.toMillis(OffsetDateTime.now().getOffset().getTotalSeconds())); calendar.set(Calendar.HOUR, 10); calendar.set(Calendar.MINUTE, 10); calendar.set(Calendar.SECOND, 10); calendar.set(Calendar.YEAR, 2025); calendar.set(Calendar.MONTH, 10); calendar.set(Calendar.DAY_OF_MONTH, 2); return calendar.getTimeInMillis(); 

4 Comments

1) the question is not about parsing a string; 2) the Calendar class should not be used anymore (one of many reason: if you compare the result of your last example with the one in the second to last: 31 days [in milliseconds]... since not doing calendar.set(Calendar.MONTH, Calendar.OCTOBER))
That is a whole lot of unnecessary work. Instead: Instant.now().toEpochMilli() solves the Question. If ISO 8601 string input were involved: Instant.parse( input ).toEpochMilli().
@BasilBourque for work in local environment - yes you dont need to use a time offsets, but when you need exactly time of event - you start thinking about time offset. Usage the "Instant", which will convert each time into "timestamp + system offset" - involves a lot of effort and time to understand "what the hell".
@user85421 1. In second part (after else) you can see code, which convert LocalDate and LocalTime into milliseconds. In second code block you can see that as well. 2. Calendar in this presentation used as example. I hope user will use another way to work with time.
-1

Simplest conversion:

Instant.from(localDateTime).toEpochMilli() 

SORRY this does not work and gies the following error:

"Unsupported field: InstantSeconds", " java.base/java.time.LocalDate.get0(LocalDate.java:708)", " java.base/java.time.LocalDate.getLong(LocalDate.java:687)", " java.base/java.time.LocalDateTime.getLong(LocalDateTime.java:720)", " java.base/java.time.Instant.from(Instant.java:373)", " com.capitalone.rupol.ruleengine.util.LocalDateSerializer.serialize(LocalDateSerializer.java:25)", "Unable to obtain Instant from TemporalAccessor: 2024-02-03T00:00 of type java.time.LocalDateTime", " java.base/java.time.Instant.from(Instant.java:378)", " com.capitalone.rupol.ruleengine.util.LocalDateSerializer.serialize(LocalDateSerializer.java:25)", " com.capitalone.rupol.ruleengine.util.LocalDateSerializer.serialize(LocalDateSerializer.java:11)", " com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeOptionalFields(MapSerializer.java:869)", " com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:760)", 

The LocalDateTime does not carry a time zone. The Instant does not carry a time zone. Strangely, many of the other conversions require specifying a time zone that you don't need. This avoids using a time zone offset at any step, and converts internally from millis to millis.

It is strange that the LocalDateTime does not offer a conversion to Instant, since both LocalDateTime and Instant do not involve any representation of a time zone, but this factory method does the job.

2 Comments

If your Answer is not correct, just delete it. Keeping it invites down-votes.
You last paragraph is incorrect. The Instant class represents a moment, a point on the timeline, as seen in UTC, an offset of zero hours-minutes-seconds. In contrast, the LocalDateTime class has no concept of time zone or offset, but is merely a date with time-of-day, nothing more. So there is no logic is trying to convert between the two. One is a moment, the other is not.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.