How to extract epoch from LocalDate and LocalDateTime?
Solution 1
The classes LocalDate
and LocalDateTime
do not contain information about the timezone or time offset, and seconds since epoch would be ambigious without this information. However, the objects have several methods to convert them into date/time objects with timezones by passing a ZoneId
instance.
LocalDate
LocalDate date = ...;
ZoneId zoneId = ZoneId.systemDefault(); // or: ZoneId.of("Europe/Oslo");
long epoch = date.atStartOfDay(zoneId).toEpochSecond();
LocalDateTime
LocalDateTime time = ...;
ZoneId zoneId = ZoneId.systemDefault(); // or: ZoneId.of("Europe/Oslo");
long epoch = time.atZone(zoneId).toEpochSecond();
Solution 2
'Millis since unix epoch' represents an instant, so you should use the Instant class:
private long toEpochMilli(LocalDateTime localDateTime)
{
return localDateTime.atZone(ZoneId.systemDefault())
.toInstant().toEpochMilli();
}
Solution 3
The conversion you need requires the offset from UTC/Greewich, or a time-zone.
If you have an offset, there is a dedicated method on LocalDateTime
for this task:
long epochSec = localDateTime.toEpochSecond(zoneOffset);
If you only have a ZoneId
then you can obtain the ZoneOffset
from the ZoneId
:
ZoneOffset zoneOffset = ZoneId.of("Europe/Oslo").getRules().getOffset(ldt);
But you may find conversion via ZonedDateTime
simpler:
long epochSec = ldt.atZone(zoneId).toEpochSecond();
Solution 4
Look at this method to see which fields are supported. You will find for LocalDateTime
:
•NANO_OF_SECOND
•NANO_OF_DAY
•MICRO_OF_SECOND
•MICRO_OF_DAY
•MILLI_OF_SECOND
•MILLI_OF_DAY
•SECOND_OF_MINUTE
•SECOND_OF_DAY
•MINUTE_OF_HOUR
•MINUTE_OF_DAY
•HOUR_OF_AMPM
•CLOCK_HOUR_OF_AMPM
•HOUR_OF_DAY
•CLOCK_HOUR_OF_DAY
•AMPM_OF_DAY
•DAY_OF_WEEK
•ALIGNED_DAY_OF_WEEK_IN_MONTH
•ALIGNED_DAY_OF_WEEK_IN_YEAR
•DAY_OF_MONTH
•DAY_OF_YEAR
•EPOCH_DAY
•ALIGNED_WEEK_OF_MONTH
•ALIGNED_WEEK_OF_YEAR
•MONTH_OF_YEAR
•PROLEPTIC_MONTH
•YEAR_OF_ERA
•YEAR
•ERA
The field INSTANT_SECONDS is - of course - not supported because a LocalDateTime
cannot refer to any absolute (global) timestamp. But what is helpful is the field EPOCH_DAY which counts the elapsed days since 1970-01-01. Similar thoughts are valid for the type LocalDate
(with even less supported fields).
If you intend to get the non-existing millis-since-unix-epoch field you also need the timezone for converting from a local to a global type. This conversion can be done much simpler, see other SO-posts.
Coming back to your question and the numbers in your code:
The result 1605 is correct
=> (2014 - 1970) * 365 + 11 (leap days) + 31 (in january 2014) + 3 (in february 2014)
The result 71461 is also correct => 19 * 3600 + 51 * 60 + 1
16105L * 86400 + 71461 = 1391543461 seconds since 1970-01-01T00:00:00 (attention, no timezone) Then you can subtract the timezone offset (watch out for possible multiplication by 1000 if in milliseconds).
UPDATE after given timezone info:
local time = 1391543461 secs
offset = 3600 secs (Europe/Oslo, winter time in february)
utc = 1391543461 - 3600 = 1391539861
As JSR-310-code with two equivalent approaches:
long secondsSinceUnixEpoch1 =
LocalDateTime.of(2014, 2, 4, 19, 51, 1).atZone(ZoneId.of("Europe/Oslo")).toEpochSecond();
long secondsSinceUnixEpoch2 =
LocalDate
.of(2014, 2, 4)
.atTime(19, 51, 1)
.atZone(ZoneId.of("Europe/Oslo"))
.toEpochSecond();
Solution 5
This is one way without using time a zone:
LocalDateTime now = LocalDateTime.now();
long epoch = (now.getLong(ChronoField.EPOCH_DAY) * 86400000) + now.getLong(ChronoField.MILLI_OF_DAY);
![Admin](/assets/logo_square_200-5d0d61d6853298bd2a4fe063103715b4daf2819fc21225efa21dfb93e61952ea.png)
Admin
Updated on July 08, 2022Comments
-
Admin almost 2 years
How do I extract the epoch value to
Long
from instances ofLocalDateTime
orLocalDate
? I've tried the following, but it gives me other results:LocalDateTime time = LocalDateTime.parse("04.02.2014 19:51:01", DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss")); System.out.println(time.getLong(ChronoField.SECOND_OF_DAY)); // gives 71461 System.out.println(time.getLong(ChronoField.EPOCH_DAY)); // gives 16105
What I want is simply the value
1391539861
for the local datetime"04.02.2014 19:51:01"
. My timezone isEurope/Oslo
UTC+1 with daylight saving time. -
Admin about 10 yearsThanks for the explanation. Got the right result by using
LocalDateTime time = LocalDateTime.parse("04.02.2014 19:51:01", DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"));
and thenLong epoch = time.atZone(ZoneId.of("Europe/Oslo")).toEpochSecond();
. -
android developer over 6 yearsIs it possible to avoid using ZoneId, or use with a customized, constant ZoneId instance (of +0 , meaning GMT) ? I ask this because I want all calculations be normalized to it. Also, how do I do the opposite: convert from epoch time to LocalDate/LocalDateTime (also without ZoneId, or with the GMT one) ?
-
android developer over 6 yearsNever mind. Found it:
ZoneId.ofOffset("UTC", ZoneOffset.ofHours(0))
-
ruhong over 6 yearsIf you only care about UTC, there is
long epochSec = localDateTime.toEpochSecond(ZoneOffset.UTC);
-
Marcus over 5 yearsA simpler approach is just
long epoch = time.toEpochSecond(ZoneOffset.UTC)
for UTC cases, or where you already know the timezone, orlong epoch = time.toEpochSecond(ZoneId.systemDefault());
if you want to go that route. -
ACV over 4 yearsit is incorrect to use
ZoneId.systemDefault()
because unix epoch refers to UTC -
Samuel Owino over 4 yearsThis might sound ridiculous but how about converting back from epoch to LocalDate, LocalTime & LocalDateTime
-
Samuel Owino over 4 yearsNever mind I think I found it;
Instant.ofEpochMilli(responseTime).atZone(ZoneId.systemDefault()).toLocalTime()
-
Dasmowenator about 4 yearsI just want to note that
ZonedDateTime
also exists and is much more useful in my experience since it can parse theZ
(or other time zones) at the end of strings into the correct time zone -
dstibbe over 3 yearsDo not use ZoneId.systemDefault ... be explicit about what you want, especially since the timezone is gone in the LocalDateTime.
-
Sourabh over 3 yearsThis doesn't answer the question.
-
Jin Kwon about 2 years@ACV Are you still agree what you once thought? Did the API designer failed to define
ZonedDateTime#toInstant
? -
ACV about 2 years@JinKwon I was merely refering to the fact that
ZoneId.systemDefault()
may not necessarily return the timezon the OP was expecting:My timezone is Europe/Oslo
. So they should useZoneId.of("Europe/Oslo")
instead as suggested in other answers. As forZonedDateTime.toInstant()
- its javadoc clearly explains the implementation:This returns an Instant representing the same point on the time-line as this date-time. The calculation combines the local date-time and offset.
-
Ernie Thomason about 2 years
ZoneId.systemDefault()
seems to return UTC, so systemDefault should be fine