Ranides Atterwim 1 год назад
Родитель
Сommit
61ded07a6e

+ 6 - 0
assira.core/src/main/java/net/ranides/assira/time2/ZoneHazard.java

@@ -1,10 +1,16 @@
 package net.ranides.assira.time2;
 package net.ranides.assira.time2;
 
 
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
 /**
  * Annotated methods can throw exception if timezone conversion is impossible due to incomplete information
  * Annotated methods can throw exception if timezone conversion is impossible due to incomplete information
  *
  *
  * If you need to use this method, think about edge cases.
  * If you need to use this method, think about edge cases.
  */
  */
+@Documented
+@Retention(RetentionPolicy.CLASS)
 public @interface ZoneHazard {
 public @interface ZoneHazard {
 
 
 }
 }

+ 32 - 52
assira.core/src/main/java/net/ranides/assira/time2/ZonedDate.java

@@ -99,18 +99,34 @@ public abstract class ZonedDate implements Comparable<ZonedDate> {
     }
     }
 
 
     public final Duration until(ZonedDateTime end) {
     public final Duration until(ZonedDateTime end) {
-        return Duration.ofMillis(until(end, ChronoUnit.MILLIS));
+        return Duration.ofNanos(until(end, ChronoUnit.NANOS));
     }
     }
 
 
-    public abstract long until(ZonedDateTime end, ChronoUnit unit);
+    public final long until(ZonedDateTime end, ChronoUnit unit) {
+        return withZero().until(end, unit);
+    }
+
+    public final Duration until(ZonedDate end) {
+        return Duration.ofNanos(until(end, ChronoUnit.NANOS));
+    }
+
+    public final long until(ZonedDate end, ChronoUnit unit) {
+        return withZero().until(end.withZero(), unit);
+    }
 
 
-    public abstract Duration until(ZonedDate end);
+    public abstract ZonedDate plus(long amount, ChronoUnit unit);
 
 
-    public abstract long until(ZonedDate end, ChronoUnit unit);
+    public final ZonedDate minus(long amount, ChronoUnit unit) {
+        return plus(-amount, unit);
+    }
 
 
-    public abstract ZonedDate plusDays(int days);
+    public final ZonedDate plusDays(int days) {
+        return plus(days, ChronoUnit.DAYS);
+    }
 
 
-    public abstract ZonedDate minusDays(int days);
+    public final ZonedDate minusDays(int days) {
+        return minus(days, ChronoUnit.DAYS);
+    }
 
 
     public abstract int getYear();
     public abstract int getYear();
 
 
@@ -146,7 +162,7 @@ public abstract class ZonedDate implements Comparable<ZonedDate> {
 
 
     @Override
     @Override
     public String toString() {
     public String toString() {
-        return DateTimeFormatters.formatDate(withZero()) + "[" + getZone() + "]";
+        return DateTimeFormatters.formatDate(withZero()) + " [" + getZone() + "]";
     }
     }
 
 
     /**
     /**
@@ -189,28 +205,8 @@ public abstract class ZonedDate implements Comparable<ZonedDate> {
         }
         }
 
 
         @Override
         @Override
-        public long until(ZonedDateTime end, ChronoUnit unit) {
-            return value.until(end, unit); // @todo
-        }
-
-        @Override
-        public Duration until(ZonedDate end) {
-            return null; // @todo
-        }
-
-        @Override
-        public long until(ZonedDate end, ChronoUnit unit) {
-            return 0; // @todo
-        }
-
-        @Override
-        public ZonedDate plusDays(int days) {
-            return new Complete(value.plusDays(days));
-        }
-
-        @Override
-        public ZonedDate minusDays(int days) {
-            return new Complete(value.minusDays(days));
+        public ZonedDate plus(long amount, ChronoUnit unit) {
+            return new Complete(value.plus(amount, unit));
         }
         }
 
 
         @Override
         @Override
@@ -252,7 +248,11 @@ public abstract class ZonedDate implements Comparable<ZonedDate> {
 
 
         @Override
         @Override
         public ZonedDate withZone(ZoneId zone) {
         public ZonedDate withZone(ZoneId zone) {
-            throw new UnsupportedOperationException();  // @todo better exception
+            if(!isSameZone(zone)) {
+                throw new UnsupportedOperationException("This date " + this + " can't be converted to " + zone);
+            } else {
+                return this;
+            }
         }
         }
 
 
         @Override
         @Override
@@ -272,28 +272,8 @@ public abstract class ZonedDate implements Comparable<ZonedDate> {
         }
         }
 
 
         @Override
         @Override
-        public long until(ZonedDateTime end, ChronoUnit unit) {
-            return 0; // @todo
-        }
-
-        @Override
-        public Duration until(ZonedDate end) {
-            return null; // @todo
-        }
-
-        @Override
-        public long until(ZonedDate end, ChronoUnit unit) {
-            return 0; // @todo
-        }
-
-        @Override
-        public ZonedDate plusDays(int days) {
-            return new Incomplete(zone, value.plusDays(days));
-        }
-
-        @Override
-        public ZonedDate minusDays(int days) {
-            return new Incomplete(zone, value.minusDays(days));
+        public ZonedDate plus(long amount, ChronoUnit unit) {
+            return new Incomplete(zone, value.plus(amount, unit));
         }
         }
 
 
         @Override
         @Override

+ 78 - 125
assira.core/src/main/java/net/ranides/assira/time2/ZonedTime.java

@@ -4,10 +4,10 @@ import lombok.RequiredArgsConstructor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.NotNull;
 
 
 import java.time.Duration;
 import java.time.Duration;
-import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.LocalTime;
 import java.time.ZoneId;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.time.ZonedDateTime;
+import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.ChronoUnit;
 
 
 public abstract class ZonedTime implements Comparable<ZonedTime> {
 public abstract class ZonedTime implements Comparable<ZonedTime> {
@@ -37,23 +37,38 @@ public abstract class ZonedTime implements Comparable<ZonedTime> {
 
 
     public abstract long toNanoOfDay();
     public abstract long toNanoOfDay();
 
 
+    @ZoneHazard
     public abstract boolean isAfter(ZonedTime other);
     public abstract boolean isAfter(ZonedTime other);
 
 
-    public abstract boolean isAfter(ZonedDateTime other);
+    public final boolean isAfter(ZonedDateTime other) {
+        return toNanoOfDay() > other.withZoneSameInstant(getZone()).toLocalTime().toNanoOfDay();
+    }
 
 
+    @ZoneHazard
     public abstract boolean isBefore(ZonedTime other);
     public abstract boolean isBefore(ZonedTime other);
 
 
-    public abstract boolean isBefore(ZonedDateTime other);
+    public final boolean isBefore(ZonedDateTime other) {
+        return toNanoOfDay() < other.withZoneSameInstant(getZone()).toLocalTime().toNanoOfDay();
+    }
 
 
+    @ZoneHazard
     public abstract boolean isEqual(ZonedTime other);
     public abstract boolean isEqual(ZonedTime other);
 
 
-    public abstract boolean isEqualTime(ZonedDateTime other);
+    public final boolean isEqualTime(ZonedDateTime other) {
+        return toNanoOfDay() == other.withZoneSameInstant(getZone()).toLocalTime().toNanoOfDay();
+    }
 
 
-    public abstract boolean isSameZone(ZonedTime other);
+    public final boolean isSameZone(ZonedTime other) {
+        return getZone().equals(other.getZone());
+    }
 
 
-    public abstract boolean isSameZone(ZonedDateTime other);
+    public final boolean isSameZone(ZonedDateTime other) {
+        return getZone().equals(other.getZone());
+    }
 
 
-    public abstract boolean isSameZone(ZoneId other);
+    public final boolean isSameZone(ZoneId other) {
+        return getZone().equals(other);
+    }
 
 
     public abstract boolean isZoneConvertible(ZoneId zone);
     public abstract boolean isZoneConvertible(ZoneId zone);
 
 
@@ -64,15 +79,24 @@ public abstract class ZonedTime implements Comparable<ZonedTime> {
     public abstract ZonedDateTime withDate(ZonedDate time);
     public abstract ZonedDateTime withDate(ZonedDate time);
 
 
     public ZonedDateTime withDate(ZonedDateTime datetime) {
     public ZonedDateTime withDate(ZonedDateTime datetime) {
-        return withDate(ZonedDate.of(datetime).withZone(getZone()));
+        return withDate(ZonedDate.of(datetime));
     }
     }
 
 
-    public abstract Duration until(ZonedDateTime end);
+    public final Duration until(ZonedDateTime end) {
+        return Duration.ofNanos(until(end, ChronoUnit.NANOS));
+    }
 
 
-    public abstract long until(ZonedDateTime end, ChronoUnit unit);
+    public final long until(ZonedDateTime end, ChronoUnit unit) {
+        long nanos = end.withZoneSameInstant(getZone()).toLocalTime().toNanoOfDay() - toNanoOfDay();
+        return nanos / unit.getDuration().toNanos();
+    }
 
 
-    public abstract Duration until(ZonedTime end);
+    @ZoneHazard
+    public final Duration until(ZonedTime end) {
+        return Duration.ofNanos(until(end, ChronoUnit.NANOS));
+    }
 
 
+    @ZoneHazard
     public abstract long until(ZonedTime end, ChronoUnit unit);
     public abstract long until(ZonedTime end, ChronoUnit unit);
 
 
     @ZoneHazard
     @ZoneHazard
@@ -87,6 +111,11 @@ public abstract class ZonedTime implements Comparable<ZonedTime> {
         return 0;
         return 0;
     }
     }
 
 
+    @Override
+    public String toString() {
+        return DateTimeFormatters.formatTime(withDate(ZonedDateTime.now())) + " [" + getZone() + "]";
+    }
+
     /**
     /**
      * This wrapper allows all operations even if timezones do not match.
      * This wrapper allows all operations even if timezones do not match.
      * Because we have full datetime, we can convert between timezones safely.
      * Because we have full datetime, we can convert between timezones safely.
@@ -103,102 +132,63 @@ public abstract class ZonedTime implements Comparable<ZonedTime> {
 
 
         @Override
         @Override
         public boolean isAfter(ZonedTime other) {
         public boolean isAfter(ZonedTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isAfter(ZonedDateTime other) {
-            return false;
+            return withZone(other.getZone()).toNanoOfDay() > other.toNanoOfDay();
         }
         }
 
 
         @Override
         @Override
         public boolean isBefore(ZonedTime other) {
         public boolean isBefore(ZonedTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isBefore(ZonedDateTime other) {
-            return false;
+            return withZone(other.getZone()).toNanoOfDay() < other.toNanoOfDay();
         }
         }
 
 
         @Override
         @Override
         public boolean isEqual(ZonedTime other) {
         public boolean isEqual(ZonedTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isEqualTime(ZonedDateTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isSameZone(ZonedTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isSameZone(ZonedDateTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isSameZone(ZoneId other) {
-            return false;
+            return withZone(other.getZone()).toNanoOfDay() == other.toNanoOfDay();
         }
         }
 
 
         @Override
         @Override
         public boolean isZoneConvertible(ZoneId zone) {
         public boolean isZoneConvertible(ZoneId zone) {
-            return false;
+            return true;
         }
         }
 
 
         @Override
         @Override
         public ZonedTime withZone(ZoneId zone) {
         public ZonedTime withZone(ZoneId zone) {
-            return null;
+            return new Complete(value.withZoneSameInstant(zone));
         }
         }
 
 
         @Override
         @Override
-        public ZonedDateTime withDate(ZonedDate time) {
-            return null;
-        }
-
-        @Override
-        public Duration until(ZonedDateTime end) {
-            return null;
-        }
-
-        @Override
-        public long until(ZonedDateTime end, ChronoUnit unit) {
-            return 0;
-        }
-
-        @Override
-        public Duration until(ZonedTime end) {
-            return null;
+        public ZonedDateTime withDate(ZonedDate date) {
+            return value
+                .withZoneSameInstant(date.getZone())
+                .withYear(date.getYear())
+                .withMonth(date.getMonth())
+                .withDayOfMonth(date.getDay())
+                .withZoneSameInstant(getZone());
         }
         }
 
 
         @Override
         @Override
         public long until(ZonedTime end, ChronoUnit unit) {
         public long until(ZonedTime end, ChronoUnit unit) {
-            return 0;
+            long nanos = end.toNanoOfDay() - withZone(end.getZone()).toNanoOfDay();
+            return nanos / unit.getDuration().toNanos();
         }
         }
 
 
         @Override
         @Override
         public int getHour() {
         public int getHour() {
-            return 0;
+            return value.getHour();
         }
         }
 
 
         @Override
         @Override
         public int getMinute() {
         public int getMinute() {
-            return 0;
+            return value.getMinute();
         }
         }
 
 
         @Override
         @Override
         public int getSecond() {
         public int getSecond() {
-            return 0;
+            return value.getSecond();
         }
         }
 
 
         @Override
         @Override
         public int getNano() {
         public int getNano() {
-            return 0;
+            return value.getNano();
         }
         }
 
 
         @Override
         @Override
@@ -220,52 +210,22 @@ public abstract class ZonedTime implements Comparable<ZonedTime> {
 
 
         @Override
         @Override
         public ZoneId getZone() {
         public ZoneId getZone() {
-            return null;
+            return zone;
         }
         }
 
 
         @Override
         @Override
         public boolean isAfter(ZonedTime other) {
         public boolean isAfter(ZonedTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isAfter(ZonedDateTime other) {
-            return false;
+            return toNanoOfDay() > other.withZone(getZone()).toNanoOfDay();
         }
         }
 
 
         @Override
         @Override
         public boolean isBefore(ZonedTime other) {
         public boolean isBefore(ZonedTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isBefore(ZonedDateTime other) {
-            return false;
+            return toNanoOfDay() < other.withZone(getZone()).toNanoOfDay();
         }
         }
 
 
         @Override
         @Override
         public boolean isEqual(ZonedTime other) {
         public boolean isEqual(ZonedTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isEqualTime(ZonedDateTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isSameZone(ZonedTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isSameZone(ZonedDateTime other) {
-            return false;
-        }
-
-        @Override
-        public boolean isSameZone(ZoneId other) {
-            return false;
+            return toNanoOfDay() == other.withZone(getZone()).toNanoOfDay();
         }
         }
 
 
         @Override
         @Override
@@ -275,52 +235,45 @@ public abstract class ZonedTime implements Comparable<ZonedTime> {
 
 
         @Override
         @Override
         public ZonedTime withZone(ZoneId zone) {
         public ZonedTime withZone(ZoneId zone) {
-            return null;
-        }
-
-        @Override
-        public ZonedDateTime withDate(ZonedDate time) {
-            return null;
-        }
-
-        @Override
-        public Duration until(ZonedDateTime end) {
-            return null;
-        }
-
-        @Override
-        public long until(ZonedDateTime end, ChronoUnit unit) {
-            return 0;
+            if(!isSameZone(zone)) {
+                throw new UnsupportedOperationException("This time " + this + " can't be converted to " + zone);
+            } else {
+                return this;
+            }
         }
         }
 
 
         @Override
         @Override
-        public Duration until(ZonedTime end) {
-            return null;
+        public ZonedDateTime withDate(ZonedDate date) {
+            return date
+                .withZone(getZone())
+                .withZero()
+                .with(ChronoField.NANO_OF_DAY, toNanoOfDay());
         }
         }
 
 
         @Override
         @Override
         public long until(ZonedTime end, ChronoUnit unit) {
         public long until(ZonedTime end, ChronoUnit unit) {
-            return 0;
+            long nanos = end.withZone(getZone()).toNanoOfDay() - toNanoOfDay();
+            return nanos / unit.getDuration().toNanos();
         }
         }
 
 
         @Override
         @Override
         public int getHour() {
         public int getHour() {
-            return 0;
+            return value.getHour();
         }
         }
 
 
         @Override
         @Override
         public int getMinute() {
         public int getMinute() {
-            return 0;
+            return value.getMinute();
         }
         }
 
 
         @Override
         @Override
         public int getSecond() {
         public int getSecond() {
-            return 0;
+            return value.getSecond();
         }
         }
 
 
         @Override
         @Override
         public int getNano() {
         public int getNano() {
-            return 0;
+            return value.getNano();
         }
         }
 
 
         @Override
         @Override

+ 24 - 0
assira.core/src/test/java/net/ranides/assira/time2/ZonedDateTest.java

@@ -0,0 +1,24 @@
+package net.ranides.assira.time2;
+
+import org.junit.Test;
+
+import java.time.LocalDate;
+
+import static org.junit.Assert.*;
+
+public class ZonedDateTest {
+
+    @Test
+    public void testWithZone() {
+        ZonedDate date = ZonedDate.of(DateTimeUtils.ZONE_PL, LocalDate.of(2020, 11, 28));
+
+        assertEquals("2020-11-28 [Poland]", date.toString());
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testWithZoneError() {
+        ZonedDate date = ZonedDate.of(DateTimeUtils.ZONE_PL, LocalDate.of(2020, 11, 28));
+
+        System.out.println(date.withZone(DateTimeUtils.ZONE_UTC));
+    }
+}

+ 38 - 0
assira.core/src/test/java/net/ranides/assira/time2/ZonedTimeTest.java

@@ -0,0 +1,38 @@
+package net.ranides.assira.time2;
+
+import org.junit.Test;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+
+import static org.junit.Assert.*;
+
+public class ZonedTimeTest {
+
+
+    @Test
+    public void testWithDate() {
+        ZonedTime time = ZonedTime.of(DateTimeUtils.ZONE_PL, LocalTime.of(14, 25, 31));
+
+        System.out.println(time);
+        System.out.println(time.withDate(ZonedDate.of(DateTimeUtils.ZONE_PL, LocalDate.of(0,1,1))));
+    }
+
+    @Test
+    public void testUntil() {
+        LocalTime timeL1 = LocalTime.of(8, 15);
+        LocalTime timeL2 = LocalTime.of(9, 20);
+
+        System.out.println(timeL1.until(timeL2, ChronoUnit.MINUTES));
+
+        ZonedTime timeA1 = ZonedTime.of(DateTimeUtils.ZONE_PL, LocalTime.of(8, 15, 0));
+        ZonedTime timeA2 = ZonedTime.of(DateTimeUtils.ZONE_PL, LocalTime.of(9, 20, 0));
+        System.out.println(timeA1.until(timeA2, ChronoUnit.MINUTES));
+
+        ZonedTime timeB1 = ZonedTime.of(ZonedDateTime.of(1980, 1, 1, 8, 15, 0, 0, DateTimeUtils.ZONE_PL));
+        ZonedTime timeB2 = ZonedTime.of(ZonedDateTime.of(1980, 1, 1, 9, 20, 0, 0, DateTimeUtils.ZONE_PL));
+        System.out.println(timeB1.until(timeB2, ChronoUnit.MINUTES));
+    }
+}