UnsupportedTemporalTypeException when formatting Instant to String
Time Zone
To format an Instant
a time-zone is required. Without a time-zone, the formatter does not know how to convert the instant to human date-time fields, and therefore throws an exception.
The time-zone can be added directly to the formatter using withZone()
.
DateTimeFormatter formatter =
DateTimeFormatter.ofLocalizedDateTime( FormatStyle.SHORT )
.withLocale( Locale.UK )
.withZone( ZoneId.systemDefault() );
If you specifically want an ISO-8601 format with no explicit time-zone
(as the OP asked), with the time-zone implicitly UTC, you need
DateTimeFormatter.ISO_LOCAL_DATE_TIME.withZone(ZoneId.from(ZoneOffset.UTC))
Generating String
Now use that formatter to generate the String representation of your Instant.
Instant instant = Instant.now();
String output = formatter.format( instant );
Dump to console.
System.out.println("formatter: " + formatter + " with zone: " + formatter.getZone() + " and Locale: " + formatter.getLocale() );
System.out.println("instant: " + instant );
System.out.println("output: " + output );
When run.
formatter: Localized(SHORT,SHORT) with zone: US/Pacific and Locale: en_GB
instant: 2015-06-02T21:34:33.616Z
output: 02/06/15 14:34
Formatting Java Instant to YYYYMMdd adds an extra year?
You want lowercase y -
System.out.println(
DateTimeFormatter.ofPattern("yyyyMMdd")
.withZone(ZoneId.of("UTC"))
.format(Instant.parse("2020-12-31T08:00:00Z"))
);
Unsupported field: Year when formatting an instant to Date ISO
To format an Instant a time-zone is required.
String input = "20161012235959.0Z";
DateTimeFormatter f = DateTimeFormatter
.ofPattern ( "uuuuMMddHHmmss.SX" )
.withLocale( Locale.FRANCE )
.withZone( ZoneId.of("UTC"));
OffsetDateTime odt = OffsetDateTime.parse ( input , f );
Instant instant = odt.toInstant ();
System.out.println(input);
System.out.print(f.format(instant));
Formatting Instant to String with specific pattern
Pattern YYYY-MM-DD'T'hh:mm'Z'
is wrong:
YYYY
- week-based-year wrong: useuuuu
yearMM
- month-of-yearDD
- day-of-year wrong: usedd
day-of-monthhh
- clock-hour-of-am-pm (1-12) without AM/PM you probably wantHH
hour-of-day (0-23)mm
- minute-of-hour
It's weird, because you even referenced a link that had the right pattern characters. Unless of course you thought upper- vs lower-case didn't matter, but if so, how did you think MM
(month) vs mm
(minute) worked?
You might want to actually read the documentation.
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds
use OffsetDateTime which has offset of the timezone and truncate it to seconds
A date-time with an offset from UTC/Greenwich in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00.
OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneId.of("Europe/Paris"));
offsetDateTime.truncatedTo(ChronoUnit.SECONDS).format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); //2020-12-29T18:28:44+01:00
If you want a custom format the build it using DateTimeFormatterBuilder
OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneOffset.UTC);
DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendOffset("+HHMM", "+0000")
.toFormatter();
offsetDateTime.truncatedTo(ChronoUnit.SECONDS).format(dateTimeFormatter); //2020-12-29T17:36:51+0000
Parse String timestamp to Instant throws Unsupported field: InstantSeconds
Here is how to get an Instant with a default time zone. Your String can not be parsed straight to Instant because timezone is missing. So you can always get the default one
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String timestamp = "2016-02-16 11:00:02";
TemporalAccessor temporalAccessor = formatter.parse(timestamp);
LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
Instant result = Instant.from(zonedDateTime);
How to get yyyy-MM-dd from an Instant object in java 8.?
I suggest to cast to a LocalDateTime
and then use DateTimeFormatter
like
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
String result = ldt.format(DateTimeFormatter.ISO_LOCAL_DATE);
You can find formatter list here, or use your own pattern
Other ways
As @Holger said in the comments, DateTimeFormatter.ISO_LOCAL_DATE.withZone(ZoneOffset.UTC)
produces a formatter that can directly format the Instant
and can be shared and reused to format a lot of instants.
static final DateTimeFormatter INSTANT_FORMATTER
= DateTimeFormatter.ISO_LOCAL_DATE.withZone(ZoneOffset.UTC);
Use like
String result = INSTANT_FORMATTER .format(instant);
@Ole V.V. mentioned that converting to LocalDateTime
as in my first snippet throws away the information about which point in time we had. We can keep that information with us when instead we convert to ZonedDateTime
or OffsetDateTime
. If you want to interpret the date in UTC (as in the previous examples), for example:
String result = instant.atOffset(ZoneOffset.UTC).format(DateTimeFormatter.ISO_LOCAL_DATE);
This makes it more explicit that the operation is dependent on the choice of UTC for interpretation.
Related Topics
Spring Security Configuration - Httpsecurity VS Websecurity
Purpose of Default or Defender Methods in Java 8
Converting Roman Numerals to Decimal
What Is the Default Encoding of the Jvm
Jdbc MySQL Connection Pooling Practices to Avoid Exhausted Connection Pool
Is It Bad to Explicitly Compare Against Boolean Constants E.G. If (B == False) in Java
Why Not to Start a Thread in the Constructor? How to Terminate
Java Date Parsing with Microsecond or Nanosecond Accuracy
Why Equals() Method When We Have == Operator
Why Were Applets Deprecated in Jdk 9
Java Annotations Values Provided in Dynamic Manner
Can't Find a Way to Color the Mandelbrot-Set the Way I'm Aiming For
How to Calculate the Number of Rows (And Columns in Each Row) a Text Takes in a Jtextarea
Java Gui Frameworks. What to Choose? Swing, Swt, Awt, Swingx, Jgoodies, Javafx, Apache Pivot