如何从 LocalDate 和 LocalDateTime 中提取 epoch?

如何从 LocalDateTimeLocalDate的实例中提取到 Long的时代值? 我已经试过了 但它给了我其他的结果:

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

我想要的只是本地日期时 "04.02.2014 19:51:01"的值 1391539861。 我的时区是世界协调时 Europe/Oslo + 1还有夏时制。

168775 次浏览

查看 这种方法,看看支持哪些字段:

•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

INSTANT _ SECONDS 字段当然不受支持,因为 LocalDateTime不能引用任何绝对(全局)时间戳。但是有用的是计算自1970-01-01以来经过的天数的字段 EPOCH _ DAY。类似的想法也适用于 LocalDate类型(支持的字段更少)。

如果您打算获取不存在的 milis-since-unix-epoch 字段,还需要时区来从局部类型转换为全局类型。这种转换可以做得更简单,见其他 职位

回到你的问题和代码中的数字:

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秒自1970-01-01 T00:00:00(注意,没有时区) 然后可以减去时区偏移量(注意可能的乘法为1000,如果以毫秒为单位)。

给定时区信息后更新:

local time = 1391543461 secs
offset = 3600 secs (Europe/Oslo, winter time in february)
utc = 1391543461 - 3600 = 1391539861

正如 JSR-310-代码有两种等价的方法:

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

LocalDateLocalDateTime不包含有关 时区时间偏移的信息,如果没有这些信息,那么由于时代将是模棱两可的。但是,通过传递一个 ZoneId实例,这些对象有几种方法可以将它们转换为带有时区的日期/时间对象。

LocalDate

LocalDate date = ...;
ZoneId zoneId = ZoneId.systemDefault(); // or: ZoneId.of("Europe/Oslo");
long epoch = date.atStartOfDay(zoneId).toEpochSecond();

本地日期时间

LocalDateTime time = ...;
ZoneId zoneId = ZoneId.systemDefault(); // or: ZoneId.of("Europe/Oslo");
long epoch = time.atZone(zoneId).toEpochSecond();

您需要的转换需要与 UTC/Greewich 的偏移量,或者一个时区。

如果你有一个偏移量,在 LocalDateTime上有一个 专用方法用于这个任务:

long epochSec = localDateTime.toEpochSecond(zoneOffset);

如果你只有一个 ZoneId,那么你可以从 ZoneId中获得 ZoneOffset:

ZoneOffset zoneOffset = ZoneId.of("Europe/Oslo").getRules().getOffset(ldt);

但你可能会发现,通过 ZonedDateTime进行转换更为简单:

long epochSec = ldt.atZone(zoneId).toEpochSecond();

“ Millis since unix epoch”表示一个即时,因此应该使用 Instant 类:

private long toEpochMilli(LocalDateTime localDateTime)
{
return localDateTime.atZone(ZoneId.systemDefault())
.toInstant().toEpochMilli();
}

人类可读日期至新纪元转换:

long epoch = new java.text.SimpleDateFormat("MM/dd/yyyyHH:mm:ss").parse("01/01/1970 01:00:00").getTime() / 1000;

世纪至人类可读日期转换:

String date = new java.text.SimpleDateFormat("MM/dd/yyyyHH:mm:ss").format(new java.util.Date (epoch*1000));

对于其他语言转换器: Https://www.epochconverter.com

这是一种不使用时间区域的方法:

LocalDateTime now = LocalDateTime.now();
long epoch = (now.getLong(ChronoField.EPOCH_DAY) * 86400000) + now.getLong(ChronoField.MILLI_OF_DAY);

提取 评论中的 两个好答案,

如果你只关心协调世界时(协调世界时) ,有

final long epoch = localDateTime.toEpochSecond(ZoneOffset.UTC);

或者你已经知道时区的地方

final long epoch = localDateTime.toEpochSecond(ZoneId.systemDefault());

更多来自 https://docs.oracle.com/javase/8/docs/api/java/time/chrono/ChronoLocalDateTime.html#toEpochSecond-java.time.ZoneOffset-的信息

ToEpochSecond

default long toEpochSecond(ZoneOffset offset)

将此日期时间转换为从 1970-01-01 T00:00:00Z.

这将此本地日期时间和指定的偏移量组合为 计算 epoch-second 值,该值是运行次数 秒从1970-01-01 T00:00:00Z 时代是正的,早期是负的。

此默认实现从日期的纪元日计算 和第二天的时间。

参数:

偏移量——用于转换的偏移量,而不是 null

返回:

1970-01-01 T00:00:00Z 纪元的秒数