如何从LocalDateTime在Java 8毫秒

我想知道是否有一种方法可以使用Java 8的新LocalDateLocalTimeLocalDateTime类来获取自1-1-1970 (epoch)以来的当前毫秒数。

已知的方法如下:

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

long currentMilliseconds = System.currentTimeMillis();
521551 次浏览

要获得以毫秒为单位的当前时间(从epoch开始),使用System.currentTimeMillis()

我不完全确定您所说的“当前毫秒”是什么意思,但我假设它是自“epoch”(即UTC 1970年1月1日午夜)以来的毫秒数。

如果你想找到自纪元现在,以来的毫秒数,那么使用System.currentTimeMillis()作为Anubian Noob指出。如果是这样,就没有理由使用任何新的java了。time api来做这个。

然而,也许你已经有了一个LocalDateTime或类似的对象,你想把它转换成从epoch到现在的毫秒数。这是不可能直接做到的,因为LocalDateTime对象家族不知道它们所在的时区。因此,需要提供时区信息来查找相对于epoch的时间,即UTC时间。

假设你有一个像这样的LocalDateTime:

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

你需要应用时区信息,给出一个ZonedDateTime。我和洛杉矶在同一个时区,所以我会这样做:

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

当然,这需要对时区进行假设。也有可能出现一些边缘情况,例如,如果当地时间恰好命名为接近日光节约时间(夏季时间)过渡的时间。我们先把这些放在一边,但你应该知道这些情况是存在的。

无论如何,如果你能得到一个有效的ZonedDateTime,你可以将其转换为自epoch以来的毫秒数,如下所示:

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

正如你所看到的,数字是相同的,除了一个小的执行时间。

以防你不喜欢系统。currentTimeMillis,使用Instant.now().toEpochMilli()

要避免ZoneId,您可以这样做:

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


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

得到0作为值,这是对的!

从Java 8开始,你可以调用java.time.Instant.toEpochMilli()

例如,调用

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

得到的结果和

final long currentTimeJava1 = System.currentTimeMillis();

你也可以使用java.sql.Timestamp来获取毫秒数。

LocalDateTime now = LocalDateTime.now();
long milliSeconds = Timestamp.valueOf(now).getTime();
System.out.println("MilliSeconds: "+milliSeconds);

如果你有一个Java 8时钟,那么你可以使用clock.millis()(尽管它建议你使用clock.instant()来获得一个Java 8即时,因为它更准确)。

为什么要使用Java 8时钟?所以在你的DI框架中,你可以创建一个时钟bean:

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

然后在你的测试中,你可以很容易地模拟它:

@MockBean private Clock clock;

或者你可以有一个不同的bean:

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

这有助于不可测量地断言日期和时间的测试。

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

为什么没有人提到LocalDateTime.toEpochSecond()方法:

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

这似乎比上面许多建议的答案要短得多……

你可以试试这个:

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

日期和时间为字符串到长(毫秒):

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

对于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)的millis。

这里有一些没有人提到的方法。但我看不出有什么理由它们不应该起作用。

对于LocalDate,可以使用toEpochDay()方法。它返回自01/01/1970以来的天数。这个数字可以很容易地转换为毫秒:

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

文档可以在在这里中找到。

对于LocalDateTime,可以使用toEpochSecond()方法。它返回自01/01/1970以来的秒数。这个数字也可以转换为毫秒:

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

它的文档是在这里