在Java-8之前,自Epoch以来,我习惯于始终将任何与日期/时间相关的内容保持为毫秒,并且只在退出时处理人类可读的日期/时间,即在UI或日志文件中,或在解析用户生成的输入时。
我认为这在Java-8中仍然是安全的,现在我正在寻找最简洁的方法来获得毫秒时间戳中的格式化日期。我试过
df = Dateformatter.ofPattern("...pattern...");
df.format(Instant.ofEpochMilli(timestamp))
但它在CCD_ 2中与CCD_。现在用什么代替Instant
?
LocalDateTime.ofEpoch(Instant, ZoneId)
似乎错了,因为我不想有当地时间。我只想在应用格式化程序时查看本地时区。在内部,它应该只是Instant
。
ZonedDateTime.ofInstant(Instant, ZoneId)
也是如此,我想只在格式化时应用ZoneId
。但我注意到DateTimeFormatter
本身似乎不再处理时区,所以我认为我需要使用上面的一个。
哪一个是首选,为什么?或者我应该使用另一种方式将epoch millis时间戳格式化为带时区的日期/时间吗?
Instant
不包含任何关于时区的信息,与其他地方不同,默认时区不会自动使用。因此,格式化程序无法计算年份,因此会出现错误消息。
因此,要格式化即时消息,必须添加时区。这可以使用Unsupported field: YearOfEra
0直接添加到格式化程序中-无需手动转换为ZonedDateTime
*:
ZoneId zone = ZoneId.systemDefault();
DateTimeFormatter df = DateTimeFormatter.ofPattern("...pattern...").withZone(zone);
df.format(Instant.ofEpochMilli(timestamp))
*遗憾的是,在早期的Java 8版本中,DateTimeformatter.withZone(ZoneId)
方法不起作用,但现在已经修复了,所以如果上面的代码不起作用的话,请升级到最新的Java 8补丁版本。
编辑:只是为了添加Instant
是当您想在没有任何其他上下文的情况下存储即时信息时使用的正确类。
使用用年份或其他字段构建的格式化程序格式化Instant
时出现的错误是意料之中的;Instant
不知道它是哪一年、哪一个月或哪一天,它只知道自大纪元以来已经过去了多少毫秒。在同一时刻,可能是地球上两个不同地方的两个不同的日子。
因此,如果您想打印当天,则需要添加时区信息。使用Instant
,可以调用atZone(zone)
将其与ZoneId
组合以形成ZonedDateTime
。这很像一个瞬间,只是它有一个时区信息。如果你想使用系统时区(运行的虚拟机的时区),你可以用Instant.getLong(...)
0来获得它。
要打印它,您可以使用两个内置的格式化程序ISO_OFFSET_DATE_TIME
或ISO_ZONED_DATE_TIME
。两者的区别在于分区日期时间格式化程序会将区域id添加到输出中。
Instant instant = Instant.now();
DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
System.out.println(formatter.format(instant.atZone(ZoneId.systemDefault())));
System.out.println(formatter.format(instant.atZone(ZoneId.of("America/Los_Angeles"))));
当在我的机器上运行时,系统时区为"Europe/Paris"
,你会得到:
2016-07-31T18:58:54.108+02:00
2016-07-31T09:58:54.108-07:00
当然,如果不适合您,您可以使用ofPattern
或构建器DateTimeFormatterBuilder
构建自己的格式化程序。
我同意这有点令人困惑,尤其是与它的前身Joda DateTime相比。
最令人困惑的是,LocalDateTime的文档说它是"一个没有时区的日期时间",而LocalDateTime.ofInstant方法同时使用即时和时区作为参数。
也就是说,我认为通过使用UTC时区,使用Instant和LocalDateTime.ofInstant可以实现您想要的目标。
public LocalDateTime millisToDateTime(long millis) {
return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of("Z");
}