|
|
@@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable;
|
|
|
import java.time.LocalDate;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.LocalTime;
|
|
|
+import java.time.OffsetTime;
|
|
|
import java.time.ZoneId;
|
|
|
import java.time.ZonedDateTime;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
@@ -20,7 +21,7 @@ public class DateTimeParsers {
|
|
|
|
|
|
public static final DateTimeFormatter ISO_ZONED = DateTimeFormatter.ISO_ZONED_DATE_TIME;
|
|
|
|
|
|
- public static final DateTimeFormatter ISO_OPTIONAL = new DateTimeFormatterBuilder()
|
|
|
+ public static final DateTimeFormatter DATETIME = new DateTimeFormatterBuilder()
|
|
|
.parseCaseInsensitive()
|
|
|
.append(DateTimeFormatter.ISO_LOCAL_DATE)
|
|
|
.appendLiteral('T')
|
|
|
@@ -36,6 +37,41 @@ public class DateTimeParsers {
|
|
|
.optionalEnd()
|
|
|
.toFormatter();
|
|
|
|
|
|
+ public static final DateTimeFormatter DATE = new DateTimeFormatterBuilder()
|
|
|
+ .parseCaseInsensitive()
|
|
|
+ .append(DateTimeFormatter.ISO_LOCAL_DATE)
|
|
|
+ .optionalStart() // time is optional
|
|
|
+ .appendLiteral('T')
|
|
|
+ .append(DateTimeFormatter.ISO_LOCAL_TIME)
|
|
|
+ .optionalStart() // zone and offset made optional
|
|
|
+ .appendOffsetId()
|
|
|
+ .optionalStart()
|
|
|
+ .appendLiteral('[')
|
|
|
+ .parseCaseSensitive()
|
|
|
+ .appendZoneRegionId()
|
|
|
+ .appendLiteral(']')
|
|
|
+ .optionalEnd()
|
|
|
+ .optionalEnd()
|
|
|
+ .optionalEnd()
|
|
|
+ .toFormatter();
|
|
|
+
|
|
|
+ public static final DateTimeFormatter TIME = new DateTimeFormatterBuilder()
|
|
|
+ .parseCaseInsensitive()
|
|
|
+ .optionalStart() // date is optional
|
|
|
+ .append(DateTimeFormatter.ISO_LOCAL_DATE)
|
|
|
+ .appendLiteral('T')
|
|
|
+ .optionalEnd()
|
|
|
+ .append(DateTimeFormatter.ISO_LOCAL_TIME)
|
|
|
+ .optionalStart() // zone and offset made optional
|
|
|
+ .appendOffsetId()
|
|
|
+ .optionalStart()
|
|
|
+ .appendLiteral('[')
|
|
|
+ .parseCaseSensitive()
|
|
|
+ .appendZoneRegionId()
|
|
|
+ .appendLiteral(']')
|
|
|
+ .optionalEnd()
|
|
|
+ .optionalEnd()
|
|
|
+ .toFormatter();
|
|
|
|
|
|
@Contract("!null -> !null; null -> null")
|
|
|
public static @Nullable ZonedDateTime parseDateTime(@Nullable String input) {
|
|
|
@@ -50,13 +86,13 @@ public class DateTimeParsers {
|
|
|
@ZoneExplicit
|
|
|
@Contract("!null -> !null; null -> null")
|
|
|
public static @Nullable ZonedDateTime parseUtcDateTime(@Nullable String input) {
|
|
|
- return parseDateTime(DateTimeUtils.ZONE_UTC, ISO_OPTIONAL, input);
|
|
|
+ return parseDateTime(DateTimeUtils.ZONE_UTC, DATETIME, input);
|
|
|
}
|
|
|
|
|
|
@ZoneExplicit
|
|
|
@Contract("!null -> !null; null -> null")
|
|
|
public static @Nullable ZonedDateTime parsePolishDateTime(@Nullable String input) {
|
|
|
- return parseDateTime(DateTimeUtils.ZONE_PL, ISO_OPTIONAL, input);
|
|
|
+ return parseDateTime(DateTimeUtils.ZONE_PL, DATETIME, input);
|
|
|
}
|
|
|
|
|
|
@ZoneExplicit
|
|
|
@@ -105,7 +141,24 @@ public class DateTimeParsers {
|
|
|
if(Objects.isNull(input)) {
|
|
|
return null;
|
|
|
}
|
|
|
- return ZonedDate.of(zone, LocalDate.parse(input, formatter));
|
|
|
+
|
|
|
+ TemporalAccessor output = formatter.parseBest(
|
|
|
+ input,
|
|
|
+ ZonedDateTime::from,
|
|
|
+ LocalDateTime::from,
|
|
|
+ LocalDate::from
|
|
|
+ );
|
|
|
+
|
|
|
+ if(output instanceof ZonedDateTime) {
|
|
|
+ return ZonedDate.of((ZonedDateTime)output).withZone(zone);
|
|
|
+ }
|
|
|
+ if(output instanceof LocalDateTime) {
|
|
|
+ return ZonedDate.of(zone, ((LocalDateTime)output).toLocalDate());
|
|
|
+ }
|
|
|
+ if(output instanceof LocalDate) {
|
|
|
+ return ZonedDate.of(zone, ((LocalDate)output));
|
|
|
+ }
|
|
|
+ throw new IllegalArgumentException();
|
|
|
}
|
|
|
|
|
|
@ZoneExplicit
|
|
|
@@ -114,7 +167,7 @@ public class DateTimeParsers {
|
|
|
if(Objects.isNull(input)) {
|
|
|
return null;
|
|
|
}
|
|
|
- return ZonedDate.of(zone, LocalDate.parse(input, DateTimeFormatters.DATE));
|
|
|
+ return parseDate(DATE, zone, input);
|
|
|
}
|
|
|
|
|
|
@ZoneExplicit
|
|
|
@@ -135,16 +188,35 @@ public class DateTimeParsers {
|
|
|
if(Objects.isNull(input)) {
|
|
|
return null;
|
|
|
}
|
|
|
- return ZonedTime.of(zone, LocalTime.parse(input, formatter));
|
|
|
+
|
|
|
+ TemporalAccessor output = formatter.parseBest(
|
|
|
+ input,
|
|
|
+ ZonedDateTime::from,
|
|
|
+ LocalDateTime::from,
|
|
|
+ OffsetTime::from,
|
|
|
+ LocalTime::from
|
|
|
+ );
|
|
|
+
|
|
|
+ if(output instanceof ZonedDateTime) {
|
|
|
+ return ZonedTime.of((ZonedDateTime) output).withZone(zone);
|
|
|
+ }
|
|
|
+ if(output instanceof LocalDateTime) {
|
|
|
+ return ZonedTime.of(zone, ((LocalDateTime)output).toLocalTime());
|
|
|
+ }
|
|
|
+ if(output instanceof OffsetTime) {
|
|
|
+ return ZonedTime.of(((OffsetTime) output).getOffset(), ((OffsetTime)output).toLocalTime());
|
|
|
+ }
|
|
|
+ if(output instanceof LocalTime) {
|
|
|
+ return ZonedTime.of(zone, (LocalTime)output);
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new IllegalArgumentException();
|
|
|
}
|
|
|
|
|
|
@ZoneExplicit
|
|
|
@Contract("_,!null -> !null; _,null -> null")
|
|
|
public static @Nullable ZonedTime parseTime(@NotNull ZoneId zone, @Nullable String input) {
|
|
|
- if(Objects.isNull(input)) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- return ZonedTime.of(zone, LocalTime.parse(input, DateTimeFormatters.TIME));
|
|
|
+ return parseTime(TIME, zone, input);
|
|
|
}
|
|
|
|
|
|
@ZoneExplicit
|