这似乎很简单,但是到目前为止,我尝试的任何方法都没有起作用。基本上,我想将以毫秒为单位的文件时间(通常)从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),因为格式化程序要打印时区值,该值在这种类型中不存在。

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

    07-26 05:17
    查看更多