ca678 преди 1 година
родител
ревизия
f43dd33334

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

@@ -62,7 +62,7 @@ public class DateTimeFormatters {
         return format(DATENAME, input);
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static String formatPolishDateShort(ZonedDateTime input) {
         return format(DATENAME, input, LOCALE_PL);
     }
@@ -71,11 +71,16 @@ public class DateTimeFormatters {
         return format(DAY_NAME, input);
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static String getPolishDayName(ZonedDateTime input) {
         return format(DAY_NAME, input, LOCALE_PL);
     }
 
+    @ZoneAware
+    public static String getPolishTime(ZonedDateTime input) {
+        return format(TIME, DateTimeUtils.withZonePolish(input));
+    }
+
     public static String format(DateTimeFormatter format, ZonedDateTime input) {
         return input == null ? null : format.format(input);
     }

+ 25 - 0
assira.core/src/main/java/net/ranides/assira/time2/DateTimeLiteral.java

@@ -0,0 +1,25 @@
+package net.ranides.assira.time2;
+
+import lombok.experimental.UtilityClass;
+
+import java.time.ZonedDateTime;
+
+@UtilityClass
+public class DateTimeLiteral {
+
+    public static ZonedTime time(int h, int m, int s) {
+        throw new UnsupportedOperationException("");
+    }
+
+    public static ZonedDate date(int y, int m, int d) {
+        throw new UnsupportedOperationException("");
+    }
+
+    public static ZonedDateTime datetime(int y, int m, int d, int H, int M) {
+        return datetime(y, m, d, H, M, 0);
+    }
+
+    public static ZonedDateTime datetime(int y, int m, int d, int H, int M, int S) {
+        return ZonedDateTime.of(y, m, d, H, M, S, 0, DateTimeUtils.ZONE_PL);
+    }
+}

+ 7 - 4
assira.core/src/main/java/net/ranides/assira/time2/DateTimeParsers.java

@@ -2,6 +2,7 @@ package net.ranides.assira.time2;
 
 import lombok.experimental.UtilityClass;
 
+import java.time.Duration;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
@@ -43,17 +44,17 @@ public class DateTimeParsers {
         return DateTimeUtils.asTime(parseDateTime(input));
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static ZonedDateTime parsePolishDateTime(String input) {
         return parse(ISO_OPTIONAL, DateTimeUtils.ZONE_PL, input);
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static ZonedDate parsePolishDate(String input) {
         return DateTimeUtils.asDate(parsePolishDateTime(input));
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static ZonedTime parsePolishTime(String input) {
         return DateTimeUtils.asTime(parsePolishDateTime(input));
     }
@@ -62,8 +63,10 @@ public class DateTimeParsers {
         return Objects.isNull(input) ? null : ZonedDateTime.parse(input, format);
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static ZonedDateTime parse(DateTimeFormatter format, ZoneId zone, String input) {
+        ZonedDateTime x = DateTimeUtils.withZoneUtc(null);
+
         if(Objects.isNull(input)) {
             return null;
         }

+ 29 - 5
assira.core/src/main/java/net/ranides/assira/time2/DateTimeUtils.java

@@ -2,6 +2,7 @@ package net.ranides.assira.time2;
 
 import lombok.experimental.UtilityClass;
 
+import java.time.Duration;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.time.temporal.ChronoUnit;
@@ -22,17 +23,17 @@ public class DateTimeUtils {
         return Locale.getDefault();
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static ZonedDateTime withZoneUtc(ZonedDateTime input) {
         return withZone(input, ZONE_UTC);
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static ZonedDateTime withZonePolish(ZonedDateTime input) {
         return withZone(input, ZONE_PL);
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static ZonedDateTime withZone(ZonedDateTime input, ZoneId zone) {
         return Objects.isNull(input) ? null : input.withZoneSameInstant(zone);
     }
@@ -41,7 +42,7 @@ public class DateTimeUtils {
         return Objects.isNull(input) ? null : ZonedTime.of(input);
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static ZonedTime asPolishTime(ZonedDateTime input) {
         return asTime(withZonePolish(input));
     }
@@ -50,7 +51,7 @@ public class DateTimeUtils {
         return Objects.isNull(input) ? null : ZonedDate.of(input);
     }
 
-    @ExplicitZone
+    @ZoneAware
     public static ZonedDate asPolishDate(ZonedDateTime input) {
         return asDate(withZonePolish(input));
     }
@@ -92,4 +93,27 @@ public class DateTimeUtils {
         throw new UnsupportedOperationException("");
     }
 
+    public static Duration diff(ZonedDateTime begin, ZonedDateTime end) {
+        if(Objects.isNull(begin) || Objects.isNull(end)) {
+            throw new IllegalArgumentException();
+        }
+        if(begin.isAfter(end)) {
+            return Duration.of(24, ChronoUnit.HOURS).minus(Duration.between(end, begin));
+        } else {
+            return Duration.between(begin, end);
+        }
+    }
+
+    @ZoneAware
+    public static Duration diff(ZonedTime begin, ZonedTime end) {
+        if(Objects.isNull(begin) || Objects.isNull(end)) {
+            throw new IllegalArgumentException();
+        }
+        if(begin.isAfter(end)) {
+            return Duration.of(24, ChronoUnit.HOURS).minus(Duration.between(end, begin));
+        } else {
+            return Duration.between(end, begin);
+        }
+    }
+
 }

+ 3 - 1
assira.core/src/main/java/net/ranides/assira/time2/ExplicitZone.java

@@ -7,8 +7,10 @@ import java.lang.annotation.Documented;
  * Annotated method explicitly enforces specific timezone. In most computations you don't need to use that information.
  *
  * If you really need to use this method, think twice about edge cases.
+ *
+ * Annotated methods can throw exception if timezone conversion is impossible due to incomplete information
  */
 @Documented
-public @interface ExplicitZone {
+public @interface ZoneAware {
 
 }

+ 72 - 2
assira.core/src/main/java/net/ranides/assira/time2/ZonedDate.java

@@ -1,11 +1,81 @@
 package net.ranides.assira.time2;
 
-import java.time.ZonedDateTime;
+import lombok.RequiredArgsConstructor;
+import org.jetbrains.annotations.NotNull;
 
-public class ZonedDate {
+import java.time.*;
+import java.util.Objects;
+
+public abstract class ZonedDate implements Comparable<ZonedDate> {
 
     public static ZonedDate of(ZonedDateTime input) {
         throw new UnsupportedOperationException("Not implemented yet");
     }
 
+    public abstract boolean isAfter(ZonedDate other);
+
+    public abstract boolean isAfter(ZonedDateTime other);
+
+    public abstract boolean isBefore(ZonedDate other);
+
+    public abstract boolean isBefore(ZonedDateTime other);
+
+    public abstract boolean isEqual(ZonedDate other);
+
+    public abstract boolean isEqual(ZonedDateTime other);
+
+    public abstract int getYear();
+
+    public abstract int getMonth();
+
+    public abstract int getDay();
+
+    @Override
+    public int compareTo(ZonedDate other) {
+        if(isEqual(other)) {
+            return 0;
+        }
+        if(isBefore(other)) {
+            return -1;
+        }
+        if(isAfter(other)) {
+            return +1;
+        }
+        throw new AssertionError("unreachable");
+    }
+
+    @Override
+    public final boolean equals(Object other) {
+        return other instanceof ZonedDate && isEqual((ZonedDate)other);
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(getYear(), getMonth(), getDay());
+    }
+
+    /**
+     * This wrapper allows all operations even if timezones do not match.
+     * Because we have full datetime, we can convert between timezones safely.
+     */
+    @RequiredArgsConstructor
+    private static abstract class Complete extends ZonedDate {
+
+        private final ZonedDateTime value;
+
+    }
+
+    /**
+     * This wrapper throws exception when timezones do not match.
+     * It is impossible to convert between timezones without full datetime.
+     */
+    @RequiredArgsConstructor
+    private static abstract class Incomplete extends ZonedDate {
+
+        private final ZoneId zone;
+
+        private final LocalDate value;
+
+    }
+
 }

+ 49 - 1
assira.core/src/main/java/net/ranides/assira/time2/ZonedTime.java

@@ -1,11 +1,59 @@
 package net.ranides.assira.time2;
 
+import lombok.RequiredArgsConstructor;
+
+import java.time.LocalTime;
+import java.time.ZoneId;
 import java.time.ZonedDateTime;
 
-public class ZonedTime {
+public abstract class ZonedTime implements Comparable<ZonedTime> {
 
     public static ZonedTime of(ZonedDateTime input) {
         throw new UnsupportedOperationException("Not implemented yet");
     }
 
+    public abstract boolean isAfter(ZonedTime other);
+
+    public abstract boolean isBefore(ZonedTime other);
+
+    public abstract boolean isEqual(ZonedTime other);
+
+    @Override
+    public int compareTo(ZonedTime other) {
+        if(isEqual(other)) {
+            return 0;
+        }
+        if(isBefore(other)) {
+            return -1;
+        }
+        if(isAfter(other)) {
+            return +1;
+        }
+        throw new AssertionError("unreachable");
+    }
+
+    /**
+     * This wrapper allows all operations even if timezones do not match.
+     * Because we have full datetime, we can convert between timezones safely.
+     */
+    @RequiredArgsConstructor
+    private static abstract class Complete extends ZonedTime {
+
+        private final ZonedDateTime value;
+
+    }
+
+    /**
+     * This wrapper throws exception when timezones do not match.
+     * It is impossible to convert between timezones without full datetime.
+     */
+    @RequiredArgsConstructor
+    private static abstract class Incomplete extends ZonedTime {
+
+        private final ZoneId zone;
+
+        private final LocalTime value;
+
+    }
+
 }

+ 0 - 29
assira.drafts/src/main/java/net/ranides/assira/datetime/DateTimeUtils1.java

@@ -60,13 +60,6 @@ public class DateTimeUtils1 {
         return LocalTime.MAX.equals(dateTime.toLocalTime());
     }
 
-    public static String extractTimeInPolishTimezone(ZonedDateTime dateTime) {
-        if (dateTime != null) {
-            return polishTime(dateTime).toLocalTime().format(TIME_FORMAT);
-        }
-        return "";
-    }
-
     public static ZonedDateTime lastDayOfMonth(ZonedDateTime date) {
         return date
                 .withDayOfMonth(1)
@@ -91,10 +84,6 @@ public class DateTimeUtils1 {
         return false;
     }
 
-    private static <T, R> R mapNullable(T value, Function<T, R> mapper) {
-        return Objects.isNull(value) ? null : mapper.apply(value);
-    }
-
     public static Duration timeDiff(LocalTime from, LocalTime to) {
         if (from.isAfter(to)) {
             return Duration.of(24, ChronoUnit.HOURS).minus(Duration.between(to, from));
@@ -102,13 +91,6 @@ public class DateTimeUtils1 {
         return Duration.between(from, to);
     }
 
-    public static Duration timeDiff(ZonedDateTime from, ZonedDateTime to) {
-        if (from.isAfter(to)) {
-            return Duration.of(24, ChronoUnit.HOURS).minus(Duration.between(to, from));
-        }
-        return Duration.between(from, to);
-    }
-
     public static Duration timeDiff(ZonedTime1 from, ZonedTime1 to) {
         if(!from.getZone().equals(to.getZone())) {
             throw new IllegalArgumentException();
@@ -119,15 +101,4 @@ public class DateTimeUtils1 {
         return Duration.between(from.getTimestamp(), to.getTimestamp());
     }
 
-    public static ZonedDate1 literal(int y, int m, int d) {
-        return ZonedDate1.from(literal(y, m, d, 0, 0, 0));
-    }
-
-    public static ZonedDateTime literal(int y, int m, int d, int H, int M) {
-        return literal(y, m, d, H, M, 0);
-    }
-
-    public static ZonedDateTime literal(int y, int m, int d, int H, int M, int S) {
-        return LocalDateTime.of(y, m, d, H, M, S).atZone(ZONE_POLAND);
-    }
 }