[Fix] Fixed ISO8601 to default to millis on toString, be lenient on parse

This commit is contained in:
Robert von Burg 2020-06-17 13:51:04 +02:00
parent 56124581ec
commit 89e11a01aa
1 changed files with 107 additions and 72 deletions

View File

@ -25,6 +25,7 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import java.util.Date;
import li.strolch.utils.helper.StringHelper;
@ -40,98 +41,82 @@ public class ISO8601 implements DateFormat {
private static final Logger logger = LoggerFactory.getLogger(ISO8601.class);
public static final Date EMPTY_VALUE = parseToDate("-");
public static final ZonedDateTime EMPTY_VALUE_ZONED_DATE = ZonedDateTime
.ofInstant(EMPTY_VALUE.toInstant(), systemDefault());
public static final DateTimeFormatter ISO_LOCAL_DATE;
private static final DateTimeFormatter _LOCAL_DATE_TIME_SECONDS;
static {
ISO_LOCAL_DATE = new DateTimeFormatterBuilder().appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) //
_LOCAL_DATE_TIME_SECONDS = new DateTimeFormatterBuilder() //
.parseCaseInsensitive() //
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) //
.appendLiteral('-') //
.appendValue(MONTH_OF_YEAR, 2) //
.appendLiteral('-') //
.appendValue(DAY_OF_MONTH, 2) //
.toFormatter();
}
public static final DateTimeFormatter ISO_LOCAL_TIME;
static {
ISO_LOCAL_TIME = new DateTimeFormatterBuilder() //
.appendLiteral('T') //
.appendValue(HOUR_OF_DAY, 2) //
.appendLiteral(':') //
.appendValue(MINUTE_OF_HOUR, 2) //
.optionalStart() //
.appendLiteral(':') //
.appendValue(SECOND_OF_MINUTE, 2) //
.toFormatter();
}
public static final DateTimeFormatter OFFSET_DATE_TIME_SECONDS;
static {
OFFSET_DATE_TIME_SECONDS = new DateTimeFormatterBuilder() //
.append(_LOCAL_DATE_TIME_SECONDS) //
.parseLenient() //
.appendOffsetId() //
.parseStrict() //
.toFormatter() //
.withZone(ZoneId.systemDefault());
}
public static final DateTimeFormatter OFFSET_DATE_TIME_MILLIS;
static {
OFFSET_DATE_TIME_MILLIS = new DateTimeFormatterBuilder() //
.append(_LOCAL_DATE_TIME_SECONDS) //
.optionalStart() //
.parseLenient() //
.appendFraction(NANO_OF_SECOND, 0, 3, true) //
.toFormatter();
.appendOffsetId() //
.parseStrict() //
.toFormatter() //
.withZone(ZoneId.systemDefault());
}
public static final DateTimeFormatter ISO_LOCAL_TIME_NO_FRACTIONS;
public static final DateTimeFormatter OFFSET_DATE_TIME_MICROS;
static {
ISO_LOCAL_TIME_NO_FRACTIONS = new DateTimeFormatterBuilder() //
.appendValue(HOUR_OF_DAY, 2) //
.appendLiteral(':') //
.appendValue(MINUTE_OF_HOUR, 2) //
OFFSET_DATE_TIME_MICROS = new DateTimeFormatterBuilder() //
.append(_LOCAL_DATE_TIME_SECONDS) //
.optionalStart() //
.appendLiteral(':') //
.appendValue(SECOND_OF_MINUTE, 2) //
.toFormatter();
}
public static final DateTimeFormatter ISO_LOCAL_DATE_TIME;
static {
ISO_LOCAL_DATE_TIME = new DateTimeFormatterBuilder() //
.parseCaseInsensitive() //
.append(ISO_LOCAL_DATE) //
.appendLiteral('T') //
.append(ISO_LOCAL_TIME) //
.toFormatter();
}
public static final DateTimeFormatter ISO_LOCAL_DATE_TIME_NO_FRACTIONS;
static {
ISO_LOCAL_DATE_TIME_NO_FRACTIONS = new DateTimeFormatterBuilder() //
.parseCaseInsensitive() //
.append(ISO_LOCAL_DATE) //
.appendLiteral('T') //
.append(ISO_LOCAL_TIME_NO_FRACTIONS) //
.toFormatter();
}
public static final DateTimeFormatter ISO_OFFSET_DATE_TIME;
static {
ISO_OFFSET_DATE_TIME = new DateTimeFormatterBuilder() //
.parseCaseInsensitive() //
.append(ISO_LOCAL_DATE_TIME) //
.parseLenient() //
.appendFraction(NANO_OF_SECOND, 0, 6, true) //
.appendOffsetId() //
.parseStrict() //
.toFormatter();
.toFormatter() //
.withZone(ZoneId.systemDefault());
}
public static final DateTimeFormatter ISO_OFFSET_DATE_TIME_ZONE;
public static final DateTimeFormatter OFFSET_DATE_TIME_NANOS;
static {
ISO_OFFSET_DATE_TIME_ZONE = ISO_OFFSET_DATE_TIME.withZone(ZoneId.systemDefault());
}
public static final DateTimeFormatter ISO_OFFSET_DATE_TIME_ZONE_NO_FRACTIONS;
static {
ISO_OFFSET_DATE_TIME_ZONE_NO_FRACTIONS = new DateTimeFormatterBuilder() //
.parseCaseInsensitive() //
.append(ISO_LOCAL_DATE_TIME_NO_FRACTIONS) //
OFFSET_DATE_TIME_NANOS = new DateTimeFormatterBuilder() //
.append(_LOCAL_DATE_TIME_SECONDS) //
.optionalStart() //
.parseLenient() //
.appendFraction(NANO_OF_SECOND, 0, 9, true) //
.appendOffsetId() //
.parseStrict() //
.toFormatter();
.toFormatter() //
.withZone(ZoneId.systemDefault());
}
@Override
@ -164,7 +149,19 @@ public class ISO8601 implements DateFormat {
return parseToDate(s);
}
public static Date parseToDate(String s) {
return Date.from(parseToZdt(s).toInstant());
}
public static ZonedDateTime parseToZdt(String s) {
return _parse(s, NANO_OF_SECOND);
}
public static ZonedDateTime parseToZdt(String s, ChronoField precision) {
return _parse(s, precision);
}
private static ZonedDateTime _parse(String s, ChronoField precision) {
if (StringHelper.isEmpty(s)) {
String msg = "An empty value can not pe parsed to a date!";
throw new IllegalArgumentException(msg);
@ -172,11 +169,7 @@ public class ISO8601 implements DateFormat {
if (s.equals("-"))
return ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
return ZonedDateTime.parse(s, getIso8601Formatter(false));
}
public static Date parseToDate(String s) {
return Date.from(parseToZdt(s).toInstant());
return ZonedDateTime.parse(s, getIso8601Formatter(precision));
}
public static String toString(LocalDateTime localDateTime) {
@ -184,22 +177,64 @@ public class ISO8601 implements DateFormat {
}
public static String toString(ZonedDateTime zonedDateTime) {
return getIso8601Formatter(false).format(zonedDateTime);
return toString(zonedDateTime, MILLI_OF_SECOND);
}
public static String toString(ZonedDateTime zonedDateTime, ChronoField precision) {
return getIso8601Formatter(precision).format(zonedDateTime);
}
public static String toString(Date date) {
return getIso8601Formatter(false).format(date.toInstant());
return getIso8601Formatter(MILLI_OF_SECOND).format(date.toInstant());
}
public static DateTimeFormatter getIso8601Formatter(boolean noFractions) {
if (noFractions)
return ISO_OFFSET_DATE_TIME_ZONE_NO_FRACTIONS;
return ISO_OFFSET_DATE_TIME_ZONE;
public static DateTimeFormatter getIso8601Formatter(ChronoField precision) {
switch (precision) {
case SECOND_OF_MINUTE:
return OFFSET_DATE_TIME_SECONDS;
case MILLI_OF_SECOND:
return OFFSET_DATE_TIME_MILLIS;
case MICRO_OF_SECOND:
return OFFSET_DATE_TIME_MICROS;
case NANO_OF_SECOND:
return OFFSET_DATE_TIME_NANOS;
default:
throw new IllegalArgumentException("Unsupported precision " + precision);
}
}
public static void main(String[] args) {
System.out.println(toString(ISO8601.parseToZdt("-")));
System.out.println(toString(parseToZdt("-")));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44+02:00")));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44+02:00", SECOND_OF_MINUTE)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44+02:00", MILLI_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44+02:00", MICRO_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44+02:00", NANO_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.234+02:00")));
// illegal: System.out.println(toString(parseToZdt("2020-06-08T18:44:44.234+02:00", SECOND_OF_MINUTE)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.234+02:00", MILLI_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.234+02:00", MICRO_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.234+02:00", NANO_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.888234+02:00")));
// illegal: System.out.println(toString(parseToZdt("2020-06-08T18:44:44.888234+02:00", SECOND_OF_MINUTE)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.888234+02:00", MILLI_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.888234+02:00", MICRO_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.888234+02:00", NANO_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.280888234+02:00")));
// illegal: System.out.println(toString(parseToZdt("2020-06-08T18:44:44.280888234+02:00", SECOND_OF_MINUTE)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.280888234+02:00", MILLI_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.280888234+02:00", MICRO_OF_SECOND)));
System.out.println(toString(parseToZdt("2020-06-08T18:44:44.280888234+02:00", NANO_OF_SECOND)));
System.out.println(toString(ZonedDateTime.now()));
System.out.println(toString(ZonedDateTime.now(), SECOND_OF_MINUTE));
System.out.println(toString(ZonedDateTime.now(), MILLI_OF_SECOND));
System.out.println(toString(ZonedDateTime.now(), MICRO_OF_SECOND));
System.out.println(toString(ZonedDateTime.now(), NANO_OF_SECOND));
System.out.println(toString(LocalDateTime.now()));
}
}