How to custom format a FileTime
Asked Answered
L

5

8

Given a FileTime fileTime, how can it be formatted in a custom way to a string?

String s = fileTime.toString() provides it in ISO format only.

String s = DateTimeFormatter.ofPattern("uuuu-MMM-dd HH:mm:ss")
                              .format(fileTime.toInstant());

throws UnsupportedTemporalTypeException: Unsupported field: Year

Lazurite answered 30/10, 2015 at 0:39 Comment(5)
did you mean yyyy instead of uuuuCursive
@Cursive I tried both. yyyy just throws Unsupported field: Year of Era instead of Unsupported field: Year.Lazurite
Did you try toMillis instead of toInstant? Formatting an Instant requires timezone.Cursive
@Cursive I tried this. How would one proceed with the result of toMillis?Lazurite
ah yes. I think your best bet is to just attach timezone to the DateTimeFormatter -- https://mcmap.net/q/81332/-unsupportedtemporaltypeexception-when-formatting-instant-to-stringCursive
S
4

You cannot format an Instant using a DateTimeFormatter instance querying the year.

An Instant is representing a single point on the time line. That's why it is not possible to give a correct/unique answer to the question "what's the year/day/time?". It depends on where on the world the question is asked: In New York it differs from Sidney. But your DateTimeFormatter is asking exactly this question. And that is why you get an UnsupportedTemporalTypeException.

You have to convert the Instance to a LocalDateTime at least:

System.out.println(timestampFormatter.format(
    LocalDateTime.ofInstant(fileTime.toInstant(), ZoneId.systemDefault()));
Saltwort answered 30/10, 2015 at 5:20 Comment(0)
L
6

Personally I find the error message "Unsupported field: Year" misleading. The real cause is missing timezone. This information is needed to help the formatter to internally convert the given instant to a human-time-representation. Solution: Supply the timezone. Then formatting or parsing an Instant is supported - in contrast to the answer of @flo.

Printing:

String s = 
  DateTimeFormatter.ofPattern("uuuu-MMM-dd HH:mm:ss", Locale.ENGLISH)
    .withZone(ZoneId.systemDefault())
    .format(Instant.now());
System.out.println(s); // 2015-Oct-30 15:22:32

Parsing:

The reverse procedure - parsing - does unfortunately not work the same direct way because the format engine of java.time is designed such that the formatter only returns a raw TemporalAccessor which needs to be converted to the real required type. Example:

Instant instant =
  Instant.from(
    DateTimeFormatter.ofPattern("uuuu-MMM-dd HH:mm:ss", Locale.ENGLISH)
    .withZone(ZoneId.systemDefault())
    .parse("2015-Oct-30 15:22:32"));
System.out.println("=>" + instant); // 2015-10-30T14:22:32Z

If the input to be parsed contains a timezone offset or an identifier then you can modify the pattern (symbols x, X, z, Z, VV etc.) and leave out the call to withZone(...), and in case of offsets - you really should leave out that call because otherwise the formatter will not use the timezone offset of your input but the supplied one zone (a pitfall I observed in my own tests).

Lucre answered 30/10, 2015 at 14:56 Comment(0)
S
4

You cannot format an Instant using a DateTimeFormatter instance querying the year.

An Instant is representing a single point on the time line. That's why it is not possible to give a correct/unique answer to the question "what's the year/day/time?". It depends on where on the world the question is asked: In New York it differs from Sidney. But your DateTimeFormatter is asking exactly this question. And that is why you get an UnsupportedTemporalTypeException.

You have to convert the Instance to a LocalDateTime at least:

System.out.println(timestampFormatter.format(
    LocalDateTime.ofInstant(fileTime.toInstant(), ZoneId.systemDefault()));
Saltwort answered 30/10, 2015 at 5:20 Comment(0)
B
2

Formatting an Instant requires a time-zone. This can be achieved using withZone(ZoneId):

String s = DateTimeFormatter.ofPattern("uuuu-MMM-dd HH:mm:ss")
                 .withZone(ZoneId.systemDefault())
                 .format(fileTime.toInstant());
Brace answered 30/10, 2015 at 14:9 Comment(0)
Y
1

If your time looks like this

2015-01-01T10:10:09

Use

yyyy-MM-dd'T'HH:mm:ss
Yuki answered 30/10, 2015 at 5:28 Comment(1)
This is not what I asked.Lazurite
N
1

ZonedDateTime can parse the default string that you get from a FileTime.toString(): (supply your own 'path' in the code snippet below)

FileTime fileTime = Files.getLastModifiedTime(path);
ZonedDateTime zonedDateTime = ZonedDateTime.parse(fileTime.toString());
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEEE, MMMM d, yyyy   HH:mm:ss");   
System.out.println(dtf.format(zonedDateTime));

Result: Saturday, April 18, 2020 13:43:29

Newel answered 18/4, 2020 at 14:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.