Browse Source

draft: datetime

ca678 1 year ago
parent
commit
c81b28495a

+ 6 - 1
assira.commons/pom.xml

@@ -53,10 +53,15 @@
             <groupId>com.fasterxml.jackson.datatype</groupId>
             <artifactId>jackson-datatype-jsr310</artifactId>
         </dependency>
+        <dependency>
+            <groupId>jakarta.persistence</groupId>
+            <artifactId>jakarta.persistence-api</artifactId>
+            <version>3.2.0</version>
+        </dependency>
         <dependency>
             <groupId>commons-net</groupId>
             <artifactId>commons-net</artifactId>
-            <version>3.4</version>
+            <version>3.11.1</version>
             <type>jar</type>
             <optional>true</optional>
         </dependency>

+ 7 - 2
assira.commons/src/main/java/net/ranides/assira/time2/DateTimeFormatters.java

@@ -78,6 +78,7 @@ public class DateTimeFormatters {
     }
 
     // @todo rename to formatPolishDateHoursMinutes?
+    @ZoneExplicit
     @Contract("!null -> !null; null -> null")
     public static @Nullable String formatPolishDateTime(@Nullable ZonedDateTime input) {
         return format(DATETIME, DateTimeUtils.withZonePolish(input));
@@ -88,6 +89,12 @@ public class DateTimeFormatters {
         return format(DATETIME_PRECISE, input);
     }
 
+    @ZoneExplicit
+    @Contract("!null -> !null; null -> null")
+    public static @Nullable String formatPolishDateTimePrecise(@Nullable ZonedDateTime input) {
+        return format(DATETIME_PRECISE, DateTimeUtils.withZonePolish(input));
+    }
+
     @Contract("!null -> !null; null -> null")
     public static @Nullable String formatTime(@Nullable ZonedDateTime input) {
         return format(TIME, input);
@@ -143,8 +150,6 @@ public class DateTimeFormatters {
         return format(DAY_NAME, input);
     }
 
-
-
     @ZoneExplicit
     @Contract("!null -> !null; null -> null")
     public static @Nullable String getPolishDayName(@Nullable ZonedDateTime input) {

+ 3 - 0
assira.commons/src/main/java/net/ranides/assira/time2/DateTimeLiteral.java

@@ -10,6 +10,9 @@ import java.time.ZonedDateTime;
 @UtilityClass
 public class DateTimeLiteral {
 
+    public static final ZonedDate MIN_DATE = dateUtc(1900, 1, 1);
+    public static final ZonedDate MAX_DATE = dateUtc(4000, 1, 1);
+
     public static final ZonedDateTime MIN = datetimeUtc(1900, 1, 1, 0, 0, 0);
     public static final ZonedDateTime MAX = datetimeUtc(4000, 1, 1, 0, 0, 0);
 

+ 44 - 14
assira.commons/src/main/java/net/ranides/assira/time2/DateTimeUtils.java

@@ -154,37 +154,45 @@ public class DateTimeUtils {
         }
     }
 
-    @Contract("_, null,null -> true")
-    public static boolean isBetween(@NotNull ZonedDateTime input, @Nullable ZonedDateTime begin, @Nullable ZonedDateTime end) {
-        Objects.requireNonNull(input);
+    @Contract("!null,null,null -> true; null,_,_ -> false")
+    public static boolean isBetween(@Nullable ZonedDateTime input, @Nullable ZonedDateTime begin, @Nullable ZonedDateTime end) {
+        if(Objects.isNull(input)) {
+            return false;
+        }
         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);
+    @Contract("!null,null,null -> true; null,_,_ -> false")
+    public static boolean isBetweenInclusive(@Nullable ZonedDateTime input, @Nullable ZonedDateTime begin, @Nullable ZonedDateTime end) {
+        if(Objects.isNull(input)) {
+            return false;
+        }
         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);
+    @Contract("!null,null,null -> true; null,_,_ -> false")
+    public static boolean isBetween(@Nullable ZonedDateTime input, @Nullable ZonedDate begin, @Nullable ZonedDate end) {
+        if(Objects.isNull(input)) {
+            return false;
+        }
         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);
+    @Contract("!null,null,null -> true; null,_,_ -> false")
+    public static boolean isBetweenInclusive(@Nullable ZonedDateTime input, @Nullable ZonedDate begin, @Nullable ZonedDate end) {
+        if(Objects.isNull(input)) {
+            return false;
+        }
         return (Objects.isNull(begin) || !begin.isAfter(input)) && (Objects.isNull(end) || !end.isBefore(input));
     }
 
-    @Contract("_, null -> true")
+    @Contract("_,null -> true")
     public static boolean isBefore(@NotNull ZonedDateTime input, @Nullable ZonedDateTime begin) {
         Objects.requireNonNull(input);
         return Objects.isNull(begin) || input.isBefore(begin);
     }
 
-    @Contract("_, null -> true")
+    @Contract("_,null -> true")
     public static boolean isAfter(@NotNull ZonedDateTime input, @Nullable ZonedDateTime end) {
         Objects.requireNonNull(input);
         return Objects.isNull(end) || end.isAfter(input);
@@ -238,6 +246,7 @@ public class DateTimeUtils {
     }
 
     @ZoneExplicit
+    @Deprecated
     @Contract("null -> null; !null -> !null")
     public static @Nullable ZonedDateTime withPolishMinTime(@Nullable ZonedDateTime datetime) {
         if(Objects.isNull(datetime)) {
@@ -247,6 +256,7 @@ public class DateTimeUtils {
     }
 
     @ZoneExplicit
+    @Deprecated
     @Contract("null -> null; !null -> !null")
     public static @Nullable ZonedDateTime withPolishMaxTime(@Nullable ZonedDateTime datetime) {
         if(Objects.isNull(datetime)) {
@@ -255,6 +265,26 @@ public class DateTimeUtils {
         return withZonePolish(datetime).with(LocalTime.MAX);
     }
 
+    @ZoneExplicit
+    @Deprecated
+    @Contract("null -> null; !null -> !null")
+    public static @Nullable ZonedDateTime withUtcMinTime(@Nullable ZonedDateTime datetime) {
+        if(Objects.isNull(datetime)) {
+            return null;
+        }
+        return withZoneUtc(datetime).with(LocalTime.MIN);
+    }
+
+    @ZoneExplicit
+    @Deprecated
+    @Contract("null -> null; !null -> !null")
+    public static @Nullable ZonedDateTime withUtcMaxTime(@Nullable ZonedDateTime datetime) {
+        if(Objects.isNull(datetime)) {
+            return null;
+        }
+        return withZoneUtc(datetime).with(LocalTime.MAX);
+    }
+
     @Deprecated
     @Contract("null -> null; !null -> !null")
     public static @Nullable ZonedDateTime withLastDayOfMonth(@Nullable ZonedDateTime datetime) {

+ 12 - 2
assira.commons/src/main/java/net/ranides/assira/time2/ZonedDate.java

@@ -5,7 +5,9 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import lombok.RequiredArgsConstructor;
 import net.ranides.assira.time2.json.ZonedDateDeserializer;
 import net.ranides.assira.time2.json.ZonedDateSerializer;
+import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.sql.Timestamp;
 import java.time.*;
@@ -23,7 +25,11 @@ public abstract class ZonedDate implements Comparable<ZonedDate> {
     // @todo configure spring
     //      https://stackoverflow.com/questions/7854030/configuring-objectmapper-in-spring
 
-    public static @NotNull ZonedDate of(@NotNull ZonedDateTime input) {
+    @Contract("null -> null; !null -> !null")
+    public static @Nullable ZonedDate of(@Nullable ZonedDateTime input) {
+        if(Objects.isNull(input)) {
+            return null;
+        }
         return new Complete(input);
     }
 
@@ -32,7 +38,11 @@ public abstract class ZonedDate implements Comparable<ZonedDate> {
         return new Incomplete(zone, date);
     }
 
-    public static ZonedDate of(@NotNull Timestamp source) {
+    @Contract("null -> null; !null -> !null")
+    public static @Nullable ZonedDate of(@Nullable Timestamp source) {
+        if(Objects.isNull(source)) {
+            return null;
+        }
         return of(ZoneId.systemDefault(), source);
     }
 

+ 43 - 0
assira.commons/src/main/java/net/ranides/assira/time2/ZonedDateRange.java

@@ -0,0 +1,43 @@
+package net.ranides.assira.time2;
+
+import lombok.Builder;
+
+import java.time.ZonedDateTime;
+import java.time.temporal.TemporalField;
+
+@Builder
+public class ZonedDateRange {
+
+    // @todo ranides remove or use
+
+    private final TemporalField precision;
+    private final boolean inclusive;
+    private final ZonedDate begin;
+    private final ZonedDate end;
+
+    private ZonedDateRange(TemporalField precision, boolean inclusive, ZonedDate begin, ZonedDate end) {
+        this.precision = precision;
+        this.inclusive = inclusive;
+        this.begin = begin;
+        this.end = end;
+    }
+
+    public boolean between(ZonedDateTime testedDate) {
+        // eliminate dates "before"
+        if(begin != null && begin.isBefore(testedDate)) {
+            return false;
+        }
+        if(end == null) {
+            return true;
+        }
+
+        return inclusive ? !end.isAfter(testedDate) : end.isBefore(testedDate);
+    }
+
+    public boolean between(ZonedDate testedDate) {
+        return false;
+    }
+
+
+
+}

+ 82 - 0
assira.commons/src/main/java/net/ranides/assira/time2/ZonedDateTimeRange.java

@@ -0,0 +1,82 @@
+package net.ranides.assira.time2;
+
+import java.io.Serializable;
+import java.time.ZonedDateTime;
+
+public abstract class ZonedDateTimeRange implements Serializable {
+
+    // @todo ranides remove or use
+
+    public static ZonedDateTimeRange of(ZonedDateTime begin, ZonedDateTime end) {
+        if(begin == null) {
+            return new BeginRange(end);
+        }
+        if(end == null) {
+            return new BeginRange(end);
+        }
+        return new FullRange(begin, end);
+    }
+
+    public abstract boolean between(ZonedDateTime testedDate);
+
+    public abstract boolean between(ZonedDate testedDate);
+
+    private static class EndRange extends ZonedDateTimeRange {
+        private final ZonedDateTime end;
+
+        private EndRange(ZonedDateTime end) {
+            this.end = end;
+        }
+
+        @Override
+        public boolean between(ZonedDateTime testedDate) {
+            return testedDate.isBefore(end);
+        }
+
+        @Override
+        public boolean between(ZonedDate testedDate) {
+            if(!testedDate.getZone().equals(end.getZone())) {
+                throw new IllegalArgumentException();
+            }
+            return testedDate.withMidnight().isBefore(end);
+        }
+    }
+
+    private static class BeginRange extends ZonedDateTimeRange {
+        private final ZonedDateTime begin;
+
+        private BeginRange(ZonedDateTime begin) {
+            this.begin = begin;
+        }
+
+        @Override
+        public boolean between(ZonedDateTime testedDate) {
+            return !testedDate.isBefore(begin);
+        }
+
+        @Override
+        public boolean between(ZonedDate testedDate) {
+            return !testedDate.withMidnight().isBefore(begin);
+        }
+    }
+
+    private static class FullRange extends ZonedDateTimeRange {
+        private final ZonedDateTime begin;
+        private final ZonedDateTime end;
+
+        public FullRange(ZonedDateTime begin, ZonedDateTime end) {
+            this.begin = begin;
+            this.end = end;
+        }
+
+        @Override
+        public boolean between(ZonedDateTime testedDate) {
+            return false;
+        }
+
+        @Override
+        public boolean between(ZonedDate testedDate) {
+            return false;
+        }
+    }
+}

+ 13 - 3
assira.commons/src/main/java/net/ranides/assira/time2/ZonedTime.java

@@ -5,7 +5,9 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import lombok.RequiredArgsConstructor;
 import net.ranides.assira.time2.json.ZonedTimeDeserializer;
 import net.ranides.assira.time2.json.ZonedTimeSerializer;
+import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.sql.Timestamp;
 import java.time.*;
@@ -21,7 +23,11 @@ public abstract class ZonedTime implements Comparable<ZonedTime> {
     // @todo SQL serializer
     // @todo SQL timestamp test
 
-    public static @NotNull ZonedTime of(@NotNull ZonedDateTime input) {
+    @Contract("null -> null; !null -> !null")
+    public static @Nullable ZonedTime of(@Nullable ZonedDateTime input) {
+        if(Objects.isNull(input)) {
+            return null;
+        }
         return new Complete(input);
     }
 
@@ -30,8 +36,12 @@ public abstract class ZonedTime implements Comparable<ZonedTime> {
         return new Incomplete(zone, time);
     }
 
-    public static ZonedTime of(@NotNull Timestamp source) {
-        return of(ZoneId.systemDefault(), source);
+    @Contract("null -> null; !null -> !null")
+    public static @Nullable ZonedTime of(@Nullable Timestamp input) {
+        if(Objects.isNull(input)) {
+            return null;
+        }
+        return of(ZoneId.systemDefault(), input);
     }
 
     @ZoneExplicit

+ 32 - 0
assira.commons/src/main/java/net/ranides/assira/time2/orm/ZonedDateConverter.java

@@ -0,0 +1,32 @@
+package net.ranides.assira.time2.orm;
+
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
+import net.ranides.assira.time2.ZonedDate;
+import org.jetbrains.annotations.Nullable;
+
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+
+@Converter(autoApply = true)
+public class ZonedDateConverter implements AttributeConverter<ZonedDate, Timestamp> {
+
+    @Override
+    public Timestamp convertToDatabaseColumn(@Nullable ZonedDate attribute) {
+        if(attribute == null) {
+            return null;
+        }
+        int y = attribute.getYear();
+        int m = attribute.getMonth();
+        int d = attribute.getDay();
+        return Timestamp.valueOf(LocalDateTime.of(y,m,d,0,0,0));
+    }
+
+    @Override
+    public ZonedDate convertToEntityAttribute(@Nullable Timestamp dbData) {
+        if(dbData == null) {
+            return null;
+        }
+        return ZonedDate.of(dbData);
+    }
+}