我想知道是否有办法使用 Java 8 的新
LocalDate
、LocalTime
或 LocalDateTime
类获取自 1970 年 1 月 1 日(纪元)以来的当前毫秒数。
已知的方法如下:
long currentMilliseconds = new Date().getTime();
或
long currentMilliseconds = System.currentTimeMillis();
我不太确定“当前毫秒”是什么意思,但我假设它是自“纪元”(即 UTC 时间 1970 年 1 月 1 日午夜)以来的毫秒数。
如果您想立即找到自纪元以来的毫秒数,然后使用
System.currentTimeMillis()
,就像Anubian Noob指出的那样。如果是这样,就没有理由使用任何新的 java.time API 来执行此操作。
但是,也许您已经在某个地方有一个
LocalDateTime
或类似的对象,并且您想将其转换为自纪元以来的毫秒数。直接执行此操作是不可能的,因为 LocalDateTime
系列对象不知道它们所在的时区。因此,需要提供时区信息来查找相对于纪元(UTC 格式)的时间。
假设你有一个像这样的
LocalDateTime
:
LocalDateTime ldt = LocalDateTime.of(2014, 5, 29, 18, 41, 16);
您需要应用时区信息,给出
ZonedDateTime
。我和洛杉矶在同一时区,所以我会做这样的事情:
ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/Los_Angeles"));
当然,这对时区做出了假设。并且可能会出现一些边缘情况,例如,如果本地时间碰巧指定了夏令时(夏令时)过渡附近的时间。让我们把这些放在一边,但你应该知道这些情况是存在的。
无论如何,如果您可以获得有效的
ZonedDateTime
,您可以将其转换为自纪元以来的毫秒数,如下所示:
long millis = zdt.toInstant().toEpochMilli();
我所做的就是不指定时区,
System.out.println("ldt " + LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
System.out.println("ctm " + System.currentTimeMillis());
给予
ldt 1424812121078
ctm 1424812121281
如您所见,除了执行时间较短之外,数字是相同的。
以防万一您不喜欢 System.currentTimeMillis,请使用
Instant.now().toEpochMilli()
从 Java 8 开始,您可以调用
java.time.Instant.toEpochMilli()
。
例如通话
final long currentTimeJava8 = Instant.now().toEpochMilli();
为您提供与
相同的结果final long currentTimeJava1 = System.currentTimeMillis();
为了避免使用 ZoneId,你可以这样做:
LocalDateTime date = LocalDateTime.of(1970, 1, 1, 0, 0);
System.out.println("Initial Epoch (TimeInMillis): " + date.toInstant(ZoneOffset.ofTotalSeconds(0)).toEpochMilli());
获取0作为值,没错!
您还可以使用
java.sql.Timestamp
来获取毫秒。
LocalDateTime now = LocalDateTime.now();
long milliSeconds = Timestamp.valueOf(now).getTime();
System.out.println("MilliSeconds: "+milliSeconds);
要获取当前时间(以毫秒为单位)(自纪元以来),请使用
System.currentTimeMillis()
。
你可以试试这个:
long diff = LocalDateTime.now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli();
为什么没有人提到方法
LocalDateTime.toEpochSecond()
:
LocalDateTime localDateTime = ... // whatever e.g. LocalDateTime.now()
long time2epoch = localDateTime.toEpochSecond(ZoneOffset.UTC);
这似乎比上面许多建议的答案要短得多......
如果是
LocalDate
,您可以使用toEpochDay()
方法。它返回自 1970 年 1 月 1 日以来的天数。然后该数字可以轻松转换为毫秒:
long dateInMillis = TimeUnit.DAYS.toMillis(myLocalDate.toEpochDays());
可以在此处找到文档。
如果是
LocalDateTime
,您可以使用toEpochSecond()
方法。它返回自 1970 年 1 月 1 日以来的秒数。该数字也可以转换为毫秒:
long dateTimeInMillis = TimeUnit.SECONDS.toMillis(myLocalDateTime.toEpochSeconds());
相关文档位于此处。
对于 LocalDateTime 我这样做:
LocalDateTime.of(2021,3,18,7,17,24,341000000)
.toInstant(OffsetDateTime.now().getOffset())
.toEpochMilli()
我认为这更简单:
ZonedDateTime zdt = ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault());
Assert.assertEquals(System.currentTimeMillis(), zdt.toInstant().toEpochMilli());
像 System.currentTimeMillis() 一样获取毫秒(来自 UTC)。
如果您有 Java 8 时钟,那么您可以使用
clock.millis()
(尽管建议您使用 clock.instant()
来获取 Java 8 Instant,因为它更准确)。
为什么要使用 Java 8 时钟?因此,在您的 DI 框架中,您可以创建一个 Clock bean:
@Bean
public Clock getClock() {
return Clock.systemUTC();
}
然后在你的测试中你可以轻松地模拟它:
@MockBean private Clock clock;
或者你可以有不同的豆子:
@Bean
public Clock getClock() {
return Clock.fixed(instant, zone);
}
这有助于进行无法估量的断言日期和时间的测试。
日期和时间为长整型字符串(毫秒):
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();
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();
}