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

后端 未结 3 1749
北恋
北恋 2021-01-06 00:45

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

3条回答
  •  孤独总比滥情好
    2021-01-06 01:23

    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.

提交回复
热议问题