繁体   English   中英

Java 8:将文件时间(1970年为毫秒)转换为RFC 1123格式

[英]Java 8: Convert file time (milliseconds from 1970) to RFC 1123 format

这似乎很简单,但是到目前为止,我尝试的任何方法都没有起作用。 基本上,我想将文件时间(以毫秒为单位)从1970年(通常)转换为TemporalAccessor,然后转换为RFC 1123格式的字符串。 但是,尽管我可以获得编译的示例,但仍遇到运行时错误。 例如:

// Just using 0 milliseconds time for quick and easy test
System.out.println(java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME.format(
                FileTime.from(0, TimeUnit.MILLISECONDS).toInstant()));

结果是

线程“主”中的异常java.time.temporal.UnsupportedTemporalTypeException:不支持的字段:DayOfMonth

我尝试使用不同的类(Instant,LocalTime,Date)对此进行了一些变体,但是得到的结果相同。

正确的方法是什么?

更新:最初的问题已在技术上得到解答,我意识到我需要更加具体。 我本人已经“成功”地将毫秒转换为TemporalAccessor,但是似乎该对象未处于可用状态。 尝试使用它执行我真正需要的操作时出现运行时错误,这使我相信我没有正确创建它。 那东西不见了。 要么是RFC 1123格式化程序中存在错误。

更新2:感谢Sleafar发布了有效的答案。

使用他的示例,我做的稍有不同,因为出于某种原因,我确实想要一个“完整的” TemporalAccessor来进行处理。 这是一个工作示例:

TemporalAccessor time = ZonedDateTime.ofInstant(Instant.ofEpochMilli(0),
ZoneId.systemDefault());
System.out.println(
        java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME.format(time));

Instant类型不包含时区信息。 您可以像这样为格式化程序定义时区:

System.out.println(java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME
    .withZone(ZoneId.systemDefault()).format( FileTime.from(0, TimeUnit.MILLISECONDS).toInstant()));

编辑:

实际上,有理由使用没有指定时区的格式化程序,以及表示类的日期/时间。 考虑以下示例:

ZoneId ect = ZoneId.of(ZoneId.SHORT_IDS.get("ECT"));

DateTimeFormatter f1 = DateTimeFormatter.RFC_1123_DATE_TIME;
DateTimeFormatter f2 = f1.withZone(ect);
DateTimeFormatter f3 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
DateTimeFormatter f4 = f3.withZone(ect);

LocalDateTime ldt = LocalDateTime.of(2015, 07, 21, 0, 0, 0, 0);
ZonedDateTime zdt = ZonedDateTime.of(ldt, ect);
Instant ins = zdt.toInstant();

System.out.println(f1.format(ins)); // throws exception (1)
System.out.println(f2.format(ins)); // Tue, 21 Jul 2015 00:00:00 +0200
System.out.println(f3.format(ins)); // throws exception (2)
System.out.println(f4.format(ins)); // 2015-07-21T00:00:00

System.out.println(f1.format(zdt)); // Tue, 21 Jul 2015 00:00:00 +0200
System.out.println(f2.format(zdt)); // Tue, 21 Jul 2015 00:00:00 +0200
System.out.println(f3.format(zdt)); // 2015-07-21T00:00:00
System.out.println(f4.format(zdt)); // 2015-07-21T00:00:00

System.out.println(f1.format(ldt)); // throws exception (3)
System.out.println(f2.format(ldt)); // throws exception (4)
System.out.println(f3.format(ldt)); // 2015-07-21T00:00:00
System.out.println(f4.format(ldt)); // 2015-07-21T00:00:00

ZoneId hst = ZoneId.of(ZoneId.SHORT_IDS.get("HST"));
ZonedDateTime zdt2 = ZonedDateTime.of(ldt, hst);

System.out.println(f1.format(zdt2)); // Tue, 21 Jul 2015 00:00:00 -1000
System.out.println(f2.format(zdt2)); // Tue, 21 Jul 2015 12:00:00 +0200
System.out.println(f3.format(zdt2)); // 2015-07-21T00:00:00
System.out.println(f4.format(zdt2)); // 2015-07-21T12:00:00
  • Instant表示实际的时间点,而无需参考特定的位置,因此也没有时区。 之所以引发例外(1)和(2),是因为格式化器表示特定的时间点需要一个时区以使输出对人类可读。
  • ZonedDateTime表示也分配给特定时区的实际时间点。 格式化它们完全没有问题,但请考虑最后一个示例。 如果在格式化程序中设置时区,则可能会得到不同的结果。
  • LocalDateTime不代表实际的时间点。 您甚至可以分配一个在某些时区无效的值,例如在夏令时的情况下将时钟向前推1小时。 要获得真实的时间点,您必须将其与时区结合起来(如上面的示例中所述)。 引发异常(3)和(4),因为格式化程序要打印时区值,该值在这种类型中不存在。

我不知道为什么设计人员选择在运行时而不是编译时发现所描述的问题。 也许这会使类的层次结构过于复杂。

自1970年以来的毫秒数被称为“纪元时间”,Instant具有静态方法Instant.ofEpochMilli(long)来支持以long的毫秒数进行创建。 从概念上讲,Instant表示“标准Java纪元”中的一个瞬间( long秒+ int纳秒),因此将文件时间表示为Instant是正确的JSR-310方法。

出于相同的目的,FileTime也具有fromMillis(long)静态方法。

在这种情况下,转换不是问题,而是Sleafar首先确定的缺少时区,这反映在您编辑过的问题中。

到Instant的成功转换没有问题。 问题是格式化程序。 使用ISO_INSTANT格式化程序而不是RFC_1123_DATE_TIME,那么您应该执行以下操作:

        inst = Instant.now();
        System.out.println(java.time.format.DateTimeFormatter.ISO_INSTANT
                           .format( inst ) );

-> 2015-07-20T21:11:53.001Z

如果您确实想使用RFC_1123格式,则必须声明一个时区。

要么将其附加到格式化程序:

        System.out.println(java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME
                           .withZone( ZoneOffset.UTC )
                           .format( inst ) );

或将Instant转换为ZonedDateTime:

        ZonedDateTime zdt = ZonedDateTime.ofInstant( inst, ZoneOffset.UTC );
        System.out.println(java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME
                           .format( zdt ) );

-> 2015年7月20日星期一21:11:53 GMT

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM