
com.nhl.link.rest.parser.converter.UtcDateConverter Maven / Gradle / Ivy
package com.nhl.link.rest.parser.converter;
import com.fasterxml.jackson.databind.JsonNode;
import com.nhl.link.rest.LinkRestException;
import javax.ws.rs.core.Response;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQueries;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.TimeZone;
import java.util.function.Function;
public class UtcDateConverter extends AbstractConverter {
private static final Map, UtcDateConverter>> converters;
static {
converters = new HashMap<>();
converters.put(java.util.Date.class, new UtcDateConverter<>(Function.identity()));
converters.put(java.sql.Date.class, new UtcDateConverter<>(date -> new java.sql.Date(date.getTime())));
converters.put(java.sql.Time.class, new UtcDateConverter<>(date -> new java.sql.Time(date.getTime())));
converters.put(java.sql.Timestamp.class, new UtcDateConverter<>(date -> new java.sql.Timestamp(date.getTime())));
}
public static UtcDateConverter converter() {
return converters.get(java.util.Date.class);
}
@SuppressWarnings("unchecked")
public static JsonValueConverter converter(Class targetType) {
JsonValueConverter converter = (JsonValueConverter) converters.get(targetType);
Objects.requireNonNull(converter, "Unsupported target type: " + targetType.getClass().getName());
return converter;
}
private Function normalizer;
private UtcDateConverter(Function normalizer) {
this.normalizer = normalizer;
}
public static DateParser dateParser() {
return ISODateParser.parser();
}
@Override
protected T valueNonNull(JsonNode node) {
Temporal temporal = ISODateParser.parser().fromString(node.asText());
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(0);
ZoneId zone = temporal.query(TemporalQueries.zone());
if (zone != null) {
calendar.setTimeZone(TimeZone.getTimeZone(zone));
}
if (temporal.isSupported(ChronoField.YEAR)) {
int year = temporal.get(ChronoField.YEAR);
int monthOfYear = temporal.get(ChronoField.MONTH_OF_YEAR);
int dayOfMonth = temporal.get(ChronoField.DAY_OF_MONTH);
calendar.set(year, --monthOfYear, dayOfMonth);
}
if (temporal.isSupported(ChronoField.HOUR_OF_DAY)) {
int hours = temporal.get(ChronoField.HOUR_OF_DAY);
int minutes = temporal.get(ChronoField.MINUTE_OF_HOUR);
int seconds = temporal.get(ChronoField.SECOND_OF_MINUTE);
calendar.set(Calendar.HOUR_OF_DAY, hours);
calendar.set(Calendar.MINUTE, minutes);
calendar.set(Calendar.SECOND, seconds);
}
if (temporal.isSupported(ChronoField.MILLI_OF_SECOND)) {
int millis = temporal.get(ChronoField.MILLI_OF_SECOND);
calendar.setTimeInMillis(calendar.getTimeInMillis() + millis);
}
return normalizer.apply(calendar.getTime());
}
public interface DateParser {
Temporal fromString(String s);
}
private static class ISODateParser implements DateParser {
private static final ISODateParser parser = new ISODateParser();
public static DateParser parser() {
return parser;
}
private DateTimeFormatter isoFormatter;
private ISODateParser() {
this.isoFormatter = new DateTimeFormatterBuilder().appendOptional(DateTimeFormatter.ISO_LOCAL_DATE)
.appendOptional(new DateTimeFormatterBuilder().appendLiteral("T").toFormatter())
.appendOptional(new DateTimeFormatterBuilder().append(DateTimeFormatter.ISO_LOCAL_TIME).toFormatter())
.appendOptional(new DateTimeFormatterBuilder().appendZoneOrOffsetId().toFormatter())
.appendOptional(new DateTimeFormatterBuilder().appendLiteral('[').parseCaseSensitive()
.appendZoneRegionId().appendLiteral(']').toFormatter()).toFormatter().withZone(ZoneId.systemDefault());
}
@Override
public Temporal fromString(String s) {
return fromParsed(isoFormatter.parse(s));
}
Temporal fromParsed(TemporalAccessor parsed) {
Optional zonedDateTime = getZonedDateTime(parsed);
if (zonedDateTime.isPresent()) {
return zonedDateTime.get();
}
Optional localDateTime = getLocalDateTime(parsed);
if (localDateTime.isPresent()) {
return localDateTime.get();
}
Optional localDate = getLocalDate(parsed);
if (localDate.isPresent()) {
return localDate.get();
}
Optional localTime = getLocalTime(parsed);
if (localTime.isPresent()) {
return localTime.get();
}
throw new LinkRestException(Response.Status.BAD_REQUEST, "Failed to build date/time/datetime: " + parsed);
}
private Optional getZonedDateTime(TemporalAccessor parsed) {
ZoneId zone = parsed.query(TemporalQueries.zone());
if (zone == null) {
return Optional.empty();
}
Optional zonedDateTime = getLocalDateTime(parsed)
.map(localDateTime -> localDateTime.atZone(zone));
if (!zonedDateTime.isPresent()) {
zonedDateTime = getLocalDate(parsed).map(localDate -> localDate.atStartOfDay(zone));
}
return zonedDateTime;
}
private Optional getLocalDateTime(TemporalAccessor parsed) {
return getLocalDate(parsed).map(date -> {
Optional time = getLocalTime(parsed);
return time.isPresent()? date.atTime(time.get()) : null;
});
}
private Optional getLocalDate(TemporalAccessor parsed) {
return Optional.ofNullable(parsed.query(TemporalQueries.localDate()));
}
private Optional getLocalTime(TemporalAccessor parsed) {
return Optional.ofNullable(parsed.query(TemporalQueries.localTime()));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy