package com.astamuse.asta4d.data.convertor;
import static java.time.temporal.ChronoField.INSTANT_SECONDS;
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
import java.time.DateTimeException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.TemporalAccessor;
import java.util.Objects;
public class String2Java8Instant extends AbstractString2Java8DateConvertor<Instant> implements DataValueConvertor<String, Instant> {
//@formatter:off
private static final DateTimeFormatter ISO_DATE_TIME_ZONE_VARIANT = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.optionalStart()
.appendOffset("+HHmm", "Z")
.optionalStart()
.appendLiteral('[')
.parseCaseSensitive()
.appendZoneRegionId()
.appendLiteral(']')
.toFormatter();
//@formatter:on
//@formatter:off
static final DateTimeFormatter[] dtfs = new DateTimeFormatter[] {
DateTimeFormatter.ofPattern("yyyyMMdd"),
DateTimeFormatter.ISO_INSTANT,
DateTimeFormatter.ISO_DATE_TIME,
ISO_DATE_TIME_ZONE_VARIANT,
DateTimeFormatter.ISO_LOCAL_DATE_TIME,
DateTimeFormatter.ISO_DATE,
DateTimeFormatter.ISO_LOCAL_DATE,
DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss.SSSZ"),
DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss.SSS"),
DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss"),
};
//@formatter:on
protected DateTimeFormatter[] availableFormatters() {
return dtfs;
}
@Override
protected Instant convert2Target(DateTimeFormatter formatter, String obj) {
TemporalAccessor temporal = formatter.parse(obj);
if (temporal instanceof Instant) {
return (Instant) temporal;
}
Objects.requireNonNull(temporal, "temporal");
try {
long instantSecs = temporal.getLong(INSTANT_SECONDS);
int nanoOfSecond = temporal.get(NANO_OF_SECOND);
return Instant.ofEpochSecond(instantSecs, nanoOfSecond);
} catch (DateTimeException e) {
// which means it may be a local date time or local date only string
ZonedDateTime zdt;
try {
LocalDateTime ldt = LocalDateTime.from(temporal);
zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
} catch (DateTimeException ex) {
// a local date only string
zdt = ZonedDateTime.of(LocalDate.from(temporal).atStartOfDay(), ZoneId.systemDefault());
}
return zdt.toInstant();
}
}
}