org.zodiac.netty.http.headers.DateTimeHeader Maven / Gradle / Ivy
The newest version!
package org.zodiac.netty.http.headers;
import java.text.ParseException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.util.Objects;
import org.zodiac.sdk.toolkit.text.ConcurrentDateFormat;
import org.zodiac.sdk.toolkit.util.lang.StrUtil;
class DateTimeHeader extends AbstractHeader implements TimestampHeader {
static final ZoneId GMT = ZoneId.of("Z");
private final ConcurrentDateFormat dateFormat = new ConcurrentDateFormat();
DateTimeHeader(CharSequence name) {
super(ZonedDateTime.class, name);
}
@Override
public String toString(ZonedDateTime value) {
Objects.requireNonNull(value, "value");
value = value.withZoneSameInstant(ZoneId.systemDefault());
return Headers.toISO2822Date(value);
}
private ZonedDateTime mungeYear(ZonedDateTime dt) {
int yr = dt.get(ChronoField.YEAR);
if (yr < 100 && yr >= 0) {
if (yr >= 50) {
yr += 1900;
} else {
yr += 2000;
}
dt = dt.withYear(yr);
}
return dt;
}
@Override
public ZonedDateTime toValue(CharSequence value) {
Objects.requireNonNull(value, "value");
/*Be permissive in what you accept, as they say*/
long val;
ZonedDateTime result;
try {
ZonedDateTime top = ZonedDateTime.parse(value, Headers.ISO2822DateFormat);
result = mungeYear(top);
} catch (DateTimeParseException e) {
try {
ZonedDateTime rfs = ZonedDateTime.parse(value, DateTimeFormatter.RFC_1123_DATE_TIME);
result = mungeYear(rfs);
} catch (DateTimeParseException e1) {
e.addSuppressed(e1);
try {
CharSequence munged = value;
int space = StrUtil.indexOf(munged, ' ');
if (space != -1) {
munged = value.subSequence(space + 1, value.length());
}
ZonedDateTime dt = ZonedDateTime.parse(munged, Headers.TWO_DIGIT_YEAR);
result = mungeYear(dt);
} catch (DateTimeParseException ex2) {
e.addSuppressed(ex2);
try {
/*Sigh...use java.util.date to handle "GMT", "PST", "EST"*/
val = dateFormat.parse(value.toString()).getTime();
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(val), ZoneId.systemDefault());
} catch (IllegalArgumentException e3) {
e.addSuppressed(e3);
new IllegalArgumentException(value.toString(), e).printStackTrace(System.err);
return null;
} catch (ParseException e2) {
e.addSuppressed(e2);
new IllegalArgumentException(value.toString(), e).printStackTrace(System.err);
return null;
}
}
}
}
// result = result.withZoneSameInstant(ZoneId.of("America/New_York"));
// ZonedDateTime result = TimeUtil.fromUnixTimestamp(val).withZoneSameInstant(Headers.UTC);
//to be truly compliant, accept 2-digit dates
// if (result.getYear() < 100 && result.getYear() > 0) {
// if (result.getYear() >= 50) {
// result = result.withYear(2_000 - (100 - result.getYear())).withDayOfYear(result.getDayOfYear() - 1); //don't ask
// } else {
// result = result.withYear(2_000 + result.getYear());
// }
// }
ZonedDateTime res = result.withZoneSameInstant(ZoneId.systemDefault());
if ("Z".equals(res.getZone().toString())) {
res = res.withZoneSameInstant(ZoneId.of("GMT"));
}
return res;
}
@Override
public TimestampHeader toInstantHeader() {
return new InstantHeader(this);
}
}