有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

datetime Java 8 epochmillis时间戳到格式化日期,如何?

在Java-8之前,我习惯于将任何与日期/时间相关的内容都保留为从Epoch开始的毫秒,并且只在退出时处理人类可读的日期/时间,即在UI或日志文件中,或者在解析用户生成的输入时

我认为这在Java-8中仍然是安全的,现在我正在寻找从毫秒时间戳中获取格式化日期的最简洁的方法。我试过了

df = Dateformatter.ofPattern("...pattern...");
df.format(Instant.ofEpochMilli(timestamp))

但它在{{}中爆炸了,这我有点理解。现在用什么来代替Instant

LocalDateTime.ofEpoch(Instant, ZoneId)似乎不对,因为我不想知道当地时间。我只想在应用格式化程序时看到本地时区。在内部,它应该只是Instant

这同样适用于ZonedDateTime.ofInstant(Instant, ZoneId),我认为只在格式化时应用ZoneId。但是我注意到DateTimeFormatter本身似乎不再处理时区,所以我认为我需要使用上面的一个

哪一个是首选的,为什么?或者我应该使用另一种方式将历元毫秒时间戳格式化为带时区的日期/时间


共 (3) 个答案

  1. # 1 楼答案

    Instant不包含任何有关时区的信息,并且与其他地方不同,默认时区不会自动使用。因此,格式化程序无法确定年份,因此会显示错误消息

    因此,要格式化即时消息,必须添加时区。可以使用^{}将其直接添加到格式化程序中-无需手动转换为ZonedDateTime*:

    ZoneId zone = ZoneId.systemDefault();
    DateTimeFormatter df = DateTimeFormatter.ofPattern("...pattern...").withZone(zone);
    df.format(Instant.ofEpochMilli(timestamp))
    

    *遗憾的是,在早期的Java 8版本中,DateTimeformatter.withZone(ZoneId)方法不起作用,但是现在已经修复了,因此如果上面的代码不起作用,请升级到最新的Java 8补丁版本

    Edit:只需添加Instant是当您希望在没有任何其他上下文的情况下存储即时消息时要使用的正确类

  2. # 2 楼答案

    我同意这有点令人困惑,尤其是与它的前身Joda DateTime相比

    最令人困惑的是,LocalDateTime的文档中说它是“没有时区的日期时间”,而LocalDateTime。ofInstant方法以瞬间和时区作为参数

    也就是说,我认为使用Instant和LocalDateTime可以实现您想要的。通过使用UTC时区进行即时更新

    public LocalDateTime millisToDateTime(long millis) {
      return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.of("Z");
    } 
    
  3. # 3 楼答案

    使用用年份或其他字段生成的格式化程序格式化Instant时可能出现错误;一个Instant不知道它是哪一年、哪一月、哪一天,它只知道从纪元开始已经过去了多少毫秒。在同一瞬间,地球上两个不同的地方可能有两个不同的日子

    因此,如果要打印日期,需要添加时区信息。使用Instant,您可以调用^{}将其与^{}组合,以形成^{}。这非常像一个瞬间,只是它有一个时区信息。如果您想使用系统时区(正在运行的VM之一),可以使用^{}获得它

    要打印它,可以使用两个内置的格式化程序^{}^{}。两者之间的区别在于分区日期时间格式化程序将向输出中添加分区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
    

    当然,如果不适合您,您可以使用^{}或生成器^{}构建自己的格式化程序