There are various options. Here’s a simple one:
private static DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS[XXX]")
.withZone(ZoneOffset.UTC);
public static Instant parse(String offsetDateTimeString) {
return OffsetDateTime.parse(offsetDateTimeString, formatter).toInstant();
}
Let’s try it out:
System.out.println(parse("2018-08-04T21:41:55.987Z"));
System.out.println(parse("2018-08-04T19:41:55.987-02:00"));
System.out.println(parse("2018-08-04T21:41:55.987"));
This prints:
2018-08-04T21:41:55.987Z
2018-08-04T21:41:55.987Z
2018-08-04T21:41:55.987Z
The square brackets in the format pattern string surround an optional part, so the offset may be present or not. Offset X
uses Z
for offset zero so matches the first two of your three formats. To specify the offset to use if there isn’t any in the string I have set a default time zone of UTC on the formatter.
Variations include:
- You may use predefined ISO formats rather than writing the entire format patterns string yourself.
- Since we are after an offset, not a time zone, it may be more correct to specify a default offset rather than a default time zone.
DateTimeFormatterBuilder
allows us to do both. So here’s a different formatter you may use in the above code instead:
private static DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendPattern("[XXX]")
.parseDefaulting(ChronoField.OFFSET_SECONDS, ZoneOffset.UTC.getTotalSeconds())
.toFormatter();
Results are identical.