If the Z
offset is optional, you can use a java.time.format.DateTimeFormatterBuilder
with an optional section:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter
.toFormatter();
Then you can use the parseBest
method, with a list of TemporalQuery
's that tries to create the correspondent object. Then you check the return type and act accordingly:
Instant instant = null;
// tries to create Instant, and if it fails, try a LocalDateTime
TemporalAccessor parsed = fmt.parseBest("2017-09-11T12:44:07.793Z", Instant::from, LocalDateTime::from);
if (parsed instanceof Instant) {
instant = (Instant) parsed;
} else if (parsed instanceof LocalDateTime) {
// convert LocalDateTime to UTC instant
instant = ((LocalDateTime) parsed).atOffset(ZoneOffset.UTC).toInstant();
}
System.out.println(instant); // 2017-09-11T12:44:07.793Z
Running with the second input (0001-01-01T00:00:00
) produces the Instant
equivalent to 0001-01-01T00:00:00Z
.
In the example above, I used just Instant::from
and LocalDateTime::from
, so the formatter tries to first create an Instant
. If it's not possible, then it tries to create a LocalDateTime
. You can add as many types you want to that list (for example, I could add ZonedDateTime::from
, and if a ZonedDateTime
is created, I could just convert to Instant
using toInstant()
method).
As you know for sure that the input is always in UTC, you can also set it directly in the formatter:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// date/time
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// optional offset
.optionalStart().appendOffsetId()
// create formatter with UTC
.toFormatter().withZone(ZoneOffset.UTC);
So you can parse it directly to Instant
:
System.out.println(Instant.from(fmt.parse("2017-09-11T12:44:07.793Z"))); // 2017-09-11T12:44:07.793Z
System.out.println(Instant.from(fmt.parse("0001-01-01T00:00:00"))); // 0001-01-01T00:00:00Z
LocalDateTime
? – GangerInstant
from0001-01-01T00:00:00
without hardcoding time zone inside the parser. – JusticiableZ
in the end of the input string. It's ok to hardcode UTC in the code. Your answer is correct and looks like it work for me with small additions – EarthaZ
makes your intentions quite clear in very little code: Correcting faulty input data. – Thrombo