How can I create a Java 8 LocalDate from a long Epoch time in Milliseconds?
我有一个外部API返回我的日期为longs,表示为自epoch以来的毫秒数。
使用旧的Java API,我只需从中构造一个EDCOX1,1个
在Java 8的EDCOX1×2 /EDCOX1×3类中,等价的是什么?
我有兴趣将long表示的时间点转换为当前本地时区中的LocalDate。
- 好吧,你必须从计算出你关心的时区开始。"从epoch开始的毫秒数"值会给您一个时间瞬间…这可能指的是不同时区的不同日期。记住,java.util.Date从来不是像LocalDate那样真正的日期——它也是一个瞬间。
- 检查这个问题:stackoverflow.com/questions/21242110/…,它包含了java.util.Date到LocalDate的转换。
- 注:对于那些试图将File.lastModified()转换为LocalDate(Time)的人来说,这个问题也很有价值。
如果您有自epoch以来的毫秒数,并且希望使用当前本地时区将其转换为本地日期,则可以使用
1 2
| LocalDate date =
Instant.ofEpochMilli(longValue).atZone(ZoneId.systemDefault()).toLocalDate(); |
但请记住,即使是系统的默认时区也可能发生变化,因此相同的long值可能会在随后的运行中产生不同的结果,即使是在同一台机器上。
此外,请记住,与java.util.Date不同,LocalDate实际上代表的是日期,而不是日期和时间。
否则,您可以使用LocalDateTime:
1 2
| LocalDateTime date =
LocalDateTime.ofInstant(Instant.ofEpochMilli(longValue), ZoneId.systemDefault()); |
- +我要更详细的解释。顺便说一下,即使是非系统区域也可以更改(通过TZUpdater工具或JDK更改),从而在前后产生不同的结果。
- @meno hochschild:我并没有关注硬编码时区,而是将其与用户指定的时区进行比较,从配置文件或环境变量中读取,在这些变量中,程序员自然会假定可能发生更改。硬编码时区实际上非常类似于系统默认值;程序员会认为它们永远不会改变……
- 我可以使用LocalDateTime.ofEpochSecond()和,例如milliseconds / 1000一起使用吗?
- @半神你可以,当你认为指定一个ZoneOffset比指定一个ZoneId更好时(你不能再使用ZoneId.systemDefault(),或者至少不能不将它转换为一个特定的Instant,但是当你有一个Instant时,为什么不使用LocalDateTime.ofInstant…)。
- @霍尔格,我有一个长的(毫秒)。为什么不能使用ZoneID.SystemDefault()?
- @半神以东x1〔8〕需要实际的以东x1〔2〕,但以东x1〔4〕返回的是以东x1〔3〕。ZoneId可以映射到不同的偏移,这取决于您所指的时间点。这就是LocalDateTime.ofInstant为您所做的,根据提供的Instant转换指定的ZoneId。
- @好的,明白了,谢谢你!
- 我来这里希望找到一个比这更易读的解决方案,从旧java.util方法降级到什么程度……
- @mihaimorcov这正是"旧java.util方法"的问题,它没有处理本地数据时间和表示瞬间的长值之间的语义差异。
- epoch定义为UTC,因此应与时区无关,因此zoneid应始终为UTC。
- @PlexQ指定的时区与纪元无关,纪元确实与时区无关,但与生成的LocalDate或LocalDateTime的语义无关。只要与这些结果对象的后续使用一致,就可以指定所需的任何时区。想想当您处理由不同方法创建的多个对象时会发生什么。本地日期或日期时间的典型使用案例包含系统默认时区,例如LocalDateTime.now()≈LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault())…
- 有些区域没有达到纳秒和毫秒。
- @FJjiaboming首先是没有纳秒的时间在epochmillis中。对于任何其他精度损失,请举出一个实际示例。
你可以从即时开始。ofepochmilli(long):
1 2 3 4
| LocalDate date =
Instant.ofEpochMilli(startDateLong)
.atZone(ZoneId.systemDefault())
.toLocalDate(); |
- +1.明确时区。如果省略,则在确定日期时将隐式应用JVM的当前默认时区。在任何特定的时刻,随着东部新的一天的到来,世界各地的日期都会随着时区的不同而变化。
我想我有更好的答案。
1
| new Timestamp(longEpochTime ). toLocalDateTime(); |
- 新时间戳(ts).ToLocalateTime().ToLocalate())
- 我的意思是,如果你不介意导入javal.q.L.TimeStand,我认为Java的单片性很好,因为它只是JVM的一部分。但感觉有点臭,但我还是更喜欢它,因为它认识到时代基本上是在UTC。
撇开时区和其他东西不谈,一个非常简单的替代方法是new Date(startDateLong),可以是LocalDate.ofEpochDay(startDateLong / 86400000L)。
- 我想你至少应该解释一下86400000是什么意思。
- 我认为很容易发现这是一天中毫秒数。
- 对某些人来说是这样,我认为只有这样才有意义,但如果不重新计算一天有多少毫秒,我就不确定了。就我自己而言,我不太清楚这个数字,所以我会自动知道它代表什么。
- 还要注意,被接受的答案确实是最好的答案,它只是看起来势不可挡。在很多情况下,我的简单黑客行为就够了。遗憾的是,java.time没有像Joda那样包括DateTimeConstants。
- java.util.concurrent.TimeUnit.MILLISECONDS.toDays(startDateLong)
- 太棒了,瓦兹姆。谢谢。
在特定情况下,如果您的epoch秒时间戳来自SQL或以某种方式与SQL相关,则可以这样获得它:
1 2 3
| long startDateLong = <... >
LocalDate theDate = new java. sql. Date(startDateLong ). toLocalDate(); |