|
@@ -1,11 +1,17 @@
|
|
|
package net.ranides.assira.time2;
|
|
package net.ranides.assira.time2;
|
|
|
|
|
|
|
|
import lombok.experimental.UtilityClass;
|
|
import lombok.experimental.UtilityClass;
|
|
|
|
|
+import org.jetbrains.annotations.Contract;
|
|
|
|
|
+import org.jetbrains.annotations.NotNull;
|
|
|
|
|
+import org.jetbrains.annotations.Nullable;
|
|
|
|
|
|
|
|
|
|
+import java.time.DayOfWeek;
|
|
|
import java.time.Duration;
|
|
import java.time.Duration;
|
|
|
|
|
+import java.time.LocalTime;
|
|
|
import java.time.ZoneId;
|
|
import java.time.ZoneId;
|
|
|
import java.time.ZonedDateTime;
|
|
import java.time.ZonedDateTime;
|
|
|
import java.time.temporal.ChronoUnit;
|
|
import java.time.temporal.ChronoUnit;
|
|
|
|
|
+import java.time.temporal.TemporalAdjusters;
|
|
|
import java.util.Locale;
|
|
import java.util.Locale;
|
|
|
import java.util.Objects;
|
|
import java.util.Objects;
|
|
|
|
|
|
|
@@ -15,48 +21,66 @@ public class DateTimeUtils {
|
|
|
public static final ZoneId ZONE_PL = ZoneId.of("Poland");
|
|
public static final ZoneId ZONE_PL = ZoneId.of("Poland");
|
|
|
public static final ZoneId ZONE_UTC = ZoneId.of("Etc/GMT0");
|
|
public static final ZoneId ZONE_UTC = ZoneId.of("Etc/GMT0");
|
|
|
|
|
|
|
|
- public static final ZonedDateTime MIN = ZonedDateTime.of(1900, 1, 1, 0, 0, 0, 0, ZONE_UTC);
|
|
|
|
|
-
|
|
|
|
|
- public static final ZonedDateTime MAX = ZonedDateTime.of(4000, 1, 1, 0, 0, 0, 0, ZONE_UTC);
|
|
|
|
|
-
|
|
|
|
|
public static Locale locale() {
|
|
public static Locale locale() {
|
|
|
return Locale.getDefault();
|
|
return Locale.getDefault();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @ZoneAware
|
|
|
|
|
- public static ZonedDateTime withZoneUtc(ZonedDateTime input) {
|
|
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @Contract("!null -> !null; null -> null")
|
|
|
|
|
+ public static @Nullable ZonedDateTime withZoneUtc(@Nullable ZonedDateTime input) {
|
|
|
return withZone(input, ZONE_UTC);
|
|
return withZone(input, ZONE_UTC);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @ZoneAware
|
|
|
|
|
- public static ZonedDateTime withZonePolish(ZonedDateTime input) {
|
|
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @Contract("!null -> !null; null -> null")
|
|
|
|
|
+ public static @Nullable ZonedDateTime withZonePolish(@Nullable ZonedDateTime input) {
|
|
|
return withZone(input, ZONE_PL);
|
|
return withZone(input, ZONE_PL);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @ZoneAware
|
|
|
|
|
- public static ZonedDateTime withZone(ZonedDateTime input, ZoneId zone) {
|
|
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @Contract("!null,_ -> !null; null,_ -> null")
|
|
|
|
|
+ public static @Nullable ZonedDateTime withZone(@Nullable ZonedDateTime input, @NotNull ZoneId zone) {
|
|
|
return Objects.isNull(input) ? null : input.withZoneSameInstant(zone);
|
|
return Objects.isNull(input) ? null : input.withZoneSameInstant(zone);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static ZonedTime asTime(ZonedDateTime input) {
|
|
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @ZoneHazard
|
|
|
|
|
+ @Contract("!null,_ -> !null; null,_ -> null")
|
|
|
|
|
+ public static @Nullable ZonedDate withZone(@Nullable ZonedDate input, @NotNull ZoneId zone) {
|
|
|
|
|
+ return Objects.isNull(input) ? null : input.withZone(zone);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @ZoneHazard
|
|
|
|
|
+ @Contract("!null,_ -> !null; null,_ -> null")
|
|
|
|
|
+ public static @Nullable ZonedTime withZone(@Nullable ZonedTime input, @NotNull ZoneId zone) {
|
|
|
|
|
+ return Objects.isNull(input) ? null : input.withZone(zone);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("!null -> !null; null -> null")
|
|
|
|
|
+ public static @Nullable ZonedTime asTime(@Nullable ZonedDateTime input) {
|
|
|
return Objects.isNull(input) ? null : ZonedTime.of(input);
|
|
return Objects.isNull(input) ? null : ZonedTime.of(input);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @ZoneAware
|
|
|
|
|
- public static ZonedTime asPolishTime(ZonedDateTime input) {
|
|
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @Contract("!null -> !null; null -> null")
|
|
|
|
|
+ public static @Nullable ZonedTime asPolishTime(@Nullable ZonedDateTime input) {
|
|
|
return asTime(withZonePolish(input));
|
|
return asTime(withZonePolish(input));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static ZonedDate asDate(ZonedDateTime input) {
|
|
|
|
|
|
|
+ @Contract("!null -> !null; null -> null")
|
|
|
|
|
+ public static @Nullable ZonedDate asDate(@Nullable ZonedDateTime input) {
|
|
|
return Objects.isNull(input) ? null : ZonedDate.of(input);
|
|
return Objects.isNull(input) ? null : ZonedDate.of(input);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @ZoneAware
|
|
|
|
|
- public static ZonedDate asPolishDate(ZonedDateTime input) {
|
|
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @Contract("!null -> !null; null -> null")
|
|
|
|
|
+ public static @Nullable ZonedDate asPolishDate(@Nullable ZonedDateTime input) {
|
|
|
return asDate(withZonePolish(input));
|
|
return asDate(withZonePolish(input));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static ZonedDateTime min(ZonedDateTime date1, ZonedDateTime date2) {
|
|
|
|
|
|
|
+ @Contract("!null,_ -> !null; _,!null -> !null; null,null -> null")
|
|
|
|
|
+ public static @Nullable ZonedDateTime min(@Nullable ZonedDateTime date1, @Nullable ZonedDateTime date2) {
|
|
|
if(Objects.isNull(date1)) {
|
|
if(Objects.isNull(date1)) {
|
|
|
return date2;
|
|
return date2;
|
|
|
}
|
|
}
|
|
@@ -66,7 +90,8 @@ public class DateTimeUtils {
|
|
|
return date1.isBefore(date2) ? date2 : date1;
|
|
return date1.isBefore(date2) ? date2 : date1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static ZonedDateTime max(ZonedDateTime date1, ZonedDateTime date2) {
|
|
|
|
|
|
|
+ @Contract("!null,_ -> !null; _,!null -> !null; null,null -> null")
|
|
|
|
|
+ public static @Nullable ZonedDateTime max(@Nullable ZonedDateTime date1, @Nullable ZonedDateTime date2) {
|
|
|
if(Objects.isNull(date1)) {
|
|
if(Objects.isNull(date1)) {
|
|
|
return date2;
|
|
return date2;
|
|
|
}
|
|
}
|
|
@@ -76,27 +101,32 @@ public class DateTimeUtils {
|
|
|
return date1.isAfter(date2) ? date1 : date2;
|
|
return date1.isAfter(date2) ? date1 : date2;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static ZonedDateTime valueOrMin(ZonedDateTime input) {
|
|
|
|
|
- return Objects.isNull(input) ? MIN : input;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public static ZonedDateTime valueOrMax(ZonedDateTime input) {
|
|
|
|
|
- return Objects.isNull(input) ? MAX : input;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public static boolean isSameDate(ZonedDateTime dateTime1, ZonedDateTime dateTime2) {
|
|
|
|
|
|
|
+ @Contract("!null,null -> false; null,!null -> false; null,null -> false")
|
|
|
|
|
+ public static boolean isSameDate(@Nullable ZonedDateTime dateTime1, @Nullable ZonedDateTime dateTime2) {
|
|
|
|
|
+ if(Objects.isNull(dateTime1) != Objects.isNull(dateTime2)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(Objects.isNull(dateTime1)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
return dateTime1.truncatedTo(ChronoUnit.DAYS).isEqual(dateTime2.truncatedTo(ChronoUnit.DAYS));
|
|
return dateTime1.truncatedTo(ChronoUnit.DAYS).isEqual(dateTime2.truncatedTo(ChronoUnit.DAYS));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static boolean isSameDate(ZonedDate dateTime1, ZonedDate dateTime2) {
|
|
|
|
|
- // @todo implement
|
|
|
|
|
- throw new UnsupportedOperationException("");
|
|
|
|
|
|
|
+ @ZoneHazard
|
|
|
|
|
+ @Contract("!null,null -> false; null,!null -> false; null,null -> false")
|
|
|
|
|
+ public static boolean isSameDate(@Nullable ZonedDate date1, @Nullable ZonedDate date2) {
|
|
|
|
|
+ if(Objects.isNull(date1) != Objects.isNull(date2)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(Objects.isNull(date1)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return date1.isEqual(date2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public static Duration diff(ZonedDateTime begin, ZonedDateTime end) {
|
|
|
|
|
- if(Objects.isNull(begin) || Objects.isNull(end)) {
|
|
|
|
|
- throw new IllegalArgumentException();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ public static @NotNull Duration diff(@NotNull ZonedDateTime begin, @NotNull ZonedDateTime end) {
|
|
|
|
|
+ Objects.requireNonNull(begin);
|
|
|
|
|
+ Objects.requireNonNull(end);
|
|
|
if(begin.isAfter(end)) {
|
|
if(begin.isAfter(end)) {
|
|
|
return Duration.of(24, ChronoUnit.HOURS).minus(Duration.between(end, begin));
|
|
return Duration.of(24, ChronoUnit.HOURS).minus(Duration.between(end, begin));
|
|
|
} else {
|
|
} else {
|
|
@@ -104,17 +134,100 @@ public class DateTimeUtils {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @ZoneAware
|
|
|
|
|
- public static Duration diff(ZonedTime begin, ZonedTime end) {
|
|
|
|
|
- if(Objects.isNull(begin) || Objects.isNull(end)) {
|
|
|
|
|
- throw new IllegalArgumentException();
|
|
|
|
|
|
|
+ @ZoneHazard
|
|
|
|
|
+ public static @NotNull Duration diff(@NotNull ZonedTime begin, @NotNull ZonedTime end) {
|
|
|
|
|
+ Objects.requireNonNull(begin);
|
|
|
|
|
+ Objects.requireNonNull(end);
|
|
|
|
|
+ if(begin.isAfter(end)) {
|
|
|
|
|
+ return Duration.of(24, ChronoUnit.HOURS).minus(end.until(begin));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return end.until(begin);
|
|
|
}
|
|
}
|
|
|
-// if(begin.isAfter(end)) {
|
|
|
|
|
-// return Duration.of(24, ChronoUnit.HOURS).minus(Duration.between(end, begin));
|
|
|
|
|
-// } else {
|
|
|
|
|
-// return Duration.between(end, begin);
|
|
|
|
|
-// }
|
|
|
|
|
- throw new UnsupportedOperationException();
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("_, null,null -> true")
|
|
|
|
|
+ public static boolean isBetween(@NotNull ZonedDateTime input, @Nullable ZonedDateTime begin, @Nullable ZonedDateTime end) {
|
|
|
|
|
+ Objects.requireNonNull(input);
|
|
|
|
|
+ return (Objects.isNull(begin) || !input.isBefore(begin)) && (Objects.isNull(end) || input.isBefore(end));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("_, null,null -> true")
|
|
|
|
|
+ public static boolean isBetweenInclusive(@NotNull ZonedDateTime input, @Nullable ZonedDateTime begin, @Nullable ZonedDateTime end) {
|
|
|
|
|
+ Objects.requireNonNull(input);
|
|
|
|
|
+ return (Objects.isNull(begin) || !input.isBefore(begin)) && (Objects.isNull(end) || !input.isAfter(end));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("_, null,null -> true")
|
|
|
|
|
+ public static boolean isBetween(@NotNull ZonedDateTime input, @Nullable ZonedDate begin, @Nullable ZonedDate end) {
|
|
|
|
|
+ Objects.requireNonNull(input);
|
|
|
|
|
+ return (Objects.isNull(begin) || !begin.isAfter(input)) && (Objects.isNull(end) || end.isAfter(input));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("_, null,null -> true")
|
|
|
|
|
+ public static boolean isBetweenInclusive(@NotNull ZonedDateTime input, @Nullable ZonedDate begin, @Nullable ZonedDate end) {
|
|
|
|
|
+ Objects.requireNonNull(input);
|
|
|
|
|
+ return (Objects.isNull(begin) || !begin.isAfter(input)) && (Objects.isNull(end) || !end.isBefore(input));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ZoneHazard
|
|
|
|
|
+ public static ZonedDateTime asDateTime(@NotNull ZonedDate date, @NotNull ZonedTime time) {
|
|
|
|
|
+ Objects.requireNonNull(date);
|
|
|
|
|
+ Objects.requireNonNull(time);
|
|
|
|
|
+ return date.withTime(time);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("null -> false")
|
|
|
|
|
+ public static boolean hasMinTime(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return Objects.nonNull(datetime) && LocalTime.MIN.equals(datetime.toLocalTime());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("null -> false")
|
|
|
|
|
+ public static boolean hasMaxTime(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return Objects.nonNull(datetime) && LocalTime.MAX.equals(datetime.toLocalTime());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @Contract("null -> false")
|
|
|
|
|
+ public static boolean hasPolishMinTime(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return Objects.nonNull(datetime) && LocalTime.MIN.equals(withZonePolish(datetime).toLocalTime());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @Contract("null -> false")
|
|
|
|
|
+ public static boolean hasPolishMaxTime(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return Objects.nonNull(datetime) && LocalTime.MAX.equals(withZonePolish(datetime).toLocalTime());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("null -> null; !null -> !null")
|
|
|
|
|
+ public static @Nullable ZonedDateTime withLastDayOfMonth(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return Objects.isNull(datetime) ? null : datetime.with(TemporalAdjusters.lastDayOfMonth());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("null -> null; !null -> !null")
|
|
|
|
|
+ public static @Nullable ZonedDateTime withLastMinuteOfDay(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return Objects.isNull(datetime) ? null : datetime.withHour(23).withMinute(59).withSecond(59);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("null -> false")
|
|
|
|
|
+ public static boolean isSaturday(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return Objects.nonNull(datetime) && datetime.getDayOfWeek() == DayOfWeek.SATURDAY;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Contract("null -> false")
|
|
|
|
|
+ public static boolean isSunday(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return Objects.nonNull(datetime) && datetime.getDayOfWeek() == DayOfWeek.SATURDAY;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @Contract("null -> false")
|
|
|
|
|
+ public static boolean isPolishSaturday(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return isSaturday(withZonePolish(datetime));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ZoneExplicit
|
|
|
|
|
+ @Contract("null -> false")
|
|
|
|
|
+ public static boolean isPolishSunday(@Nullable ZonedDateTime datetime) {
|
|
|
|
|
+ return isSunday(withZonePolish(datetime));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|