This seems like it should be simple, but so far nothing I try is working. Basically I want to convert a file time in milliseconds from 1970 (the usual) to a TemporalAccessor
Milliseconds since 1970 is known as "epoch time", and Instant has the static method Instant.ofEpochMilli(long) to support creation from a long
number of milliseconds. Conceptually Instant represents a single moment (long
seconds + int
nanoseconds) in "the standard Java epoch", so representing file time as an Instant is the correct JSR-310 way to do it.
FileTime also has a fromMillis(long) static method for the same purpose.
In this case, the conversion wasn't the problem—it was the lack of timezone as Sleafar identified first, as reflected in your edited question.
The Instant
type doesn't contain timezone information. You can define a timezone for the formatter like this:
System.out.println(java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME
.withZone(ZoneId.systemDefault()).format( FileTime.from(0, TimeUnit.MILLISECONDS).toInstant()));
Edit:
Actually there are reasons to have formatters without an assigned timezone, as well as date/time representing classes. Consider the following example:
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
represents an actual point in time without referring to a specific location and therefore without a timezone. The exceptions (1) and (2) are raised because to represent the specific point in time the formatter needs a timezone to make the output readable for humans.ZonedDateTime
represents an actual point in time also assigned to a specific timezone. No problems at all to format them, but consider the last example. If you set a timezone in the formatter, you might get different results.LocalDateTime
doesn't represent an actual point in time. You can even assign a value which is invalid in some timezones, like when the clock is pushed forward 1 hour in case of daylight saving time. To get a real point in time you have to combine it with a timezone (like done in the example above). Exceptions (3) and (4) are raised, because the formatter wants to print a timezone value, which doesn't exist in this type.I can't tell why the designers opted to discover the described problems at runtime instead of compile time. Maybe it would make the class hierarchy too complicated.
The conversion to Instant succeeds without problem. The problem is the formatter. Use ISO_INSTANT formatter instead of RFC_1123_DATE_TIME then you should go:
inst = Instant.now();
System.out.println(java.time.format.DateTimeFormatter.ISO_INSTANT
.format( inst ) );
--> 2015-07-20T21:11:53.001Z
If you really want to have RFC_1123 format, you have to declare a timezone.
Either append it to the formatter :
System.out.println(java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME
.withZone( ZoneOffset.UTC )
.format( inst ) );
or convert the Instant to a ZonedDateTime:
ZonedDateTime zdt = ZonedDateTime.ofInstant( inst, ZoneOffset.UTC );
System.out.println(java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME
.format( zdt ) );
--> Mon, 20 Jul 2015 21:11:53 GMT