From 3dd23e7c0aa5806c5646a3a0f49656f496b477a6 Mon Sep 17 00:00:00 2001 From: "R. C. Howell" Date: Tue, 26 Nov 2024 16:46:35 -0500 Subject: [PATCH] Adds updated datetime and interval datums --- .../java/org/partiql/spi/datetime/Date.java | 166 -------------- .../org/partiql/spi/datetime/Interval.java | 216 ------------------ .../java/org/partiql/spi/datetime/Time.java | 150 ------------ .../org/partiql/spi/datetime/Timestamp.java | 182 --------------- .../org/partiql/spi/datetime/Timestampz.java | 163 ------------- .../java/org/partiql/spi/datetime/Timez.java | 139 ----------- .../java/org/partiql/spi/value/Datum.java | 102 +++++---- .../java/org/partiql/spi/value/DatumDate.java | 31 ++- .../org/partiql/spi/value/DatumInterval.java | 27 --- .../partiql/spi/value/DatumIntervalDT.java | 30 +++ .../partiql/spi/value/DatumIntervalYM.java | 30 +++ .../java/org/partiql/spi/value/DatumNull.java | 72 ++++-- .../java/org/partiql/spi/value/DatumTime.java | 29 +-- .../org/partiql/spi/value/DatumTimestamp.java | 36 +-- .../partiql/spi/value/DatumTimestampz.java | 44 ++++ .../org/partiql/spi/value/DatumTimez.java | 35 +++ 16 files changed, 301 insertions(+), 1151 deletions(-) delete mode 100644 partiql-spi/src/main/java/org/partiql/spi/datetime/Date.java delete mode 100644 partiql-spi/src/main/java/org/partiql/spi/datetime/Interval.java delete mode 100644 partiql-spi/src/main/java/org/partiql/spi/datetime/Time.java delete mode 100644 partiql-spi/src/main/java/org/partiql/spi/datetime/Timestamp.java delete mode 100644 partiql-spi/src/main/java/org/partiql/spi/datetime/Timestampz.java delete mode 100644 partiql-spi/src/main/java/org/partiql/spi/datetime/Timez.java delete mode 100644 partiql-spi/src/main/java/org/partiql/spi/value/DatumInterval.java create mode 100644 partiql-spi/src/main/java/org/partiql/spi/value/DatumIntervalDT.java create mode 100644 partiql-spi/src/main/java/org/partiql/spi/value/DatumIntervalYM.java create mode 100644 partiql-spi/src/main/java/org/partiql/spi/value/DatumTimestampz.java create mode 100644 partiql-spi/src/main/java/org/partiql/spi/value/DatumTimez.java diff --git a/partiql-spi/src/main/java/org/partiql/spi/datetime/Date.java b/partiql-spi/src/main/java/org/partiql/spi/datetime/Date.java deleted file mode 100644 index 3e4cf31ea..000000000 --- a/partiql-spi/src/main/java/org/partiql/spi/datetime/Date.java +++ /dev/null @@ -1,166 +0,0 @@ -package org.partiql.spi.datetime; - -import org.jetbrains.annotations.NotNull; - -import java.time.Clock; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; - -/** - * A PartiQL date. - *
- * This class provides basic APIs for creating a Date. More complex use-cases should create a Date from a LocalDate. - * For example, to create a `now()` Date with an alternative timezone, use: - *
- *     Clock clock = Clock.system(ZoneId.of("America/New_York"));
- *     Date date = new Date(LocalDate.now(clock));
- * 
- * This API may be extended with additional constructors to reduce verbosity, but it is intentionally lean. - */ -public class Date { - - /** - * Delegate all functionality to the JDK8+ recommend APIs, but keep this internalized. - */ - @NotNull - private final LocalDate date; - - /** - * SQL date formatter. - */ - private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - - /** - * NO PUBLIC CONSTRUCTORS. - */ - private Date(@NotNull LocalDate date) { - this.date = date; - } - - /** - * @return date for current date-time for the system clock. - */ - @NotNull - public static Date now() { - return new Date(LocalDate.now(Clock.systemDefaultZone())); - } - - /** - * Create a new Date from a {@link LocalDate}. - * - * @param date the {@link LocalDate} to wrap - */ - @NotNull - public static Date of(@NotNull LocalDate date) { - return new Date(date); - } - - /** - * Create a new Date from a year, month, and day. - * - * @param year the year to represent, from Year.MIN_YEAR to Year.MAX_YEAR - * @param month the month-of-year to represent, from 1 (January) to 12 (December) - * @param day the day of month to represent, from 1 to 31 - */ - @NotNull - public static Date of(int year, int month, int day) { - return new Date(LocalDate.of(year, month, day)); - } - - /** - * @return a {@link LocalDate} representation of this date. - */ - @NotNull - public LocalDate toLocalDate() { - return date; - } - - /** - * @return the year of this date - */ - public int getYear() { - return date.getYear(); - } - - /** - * @return the month (of the year) field value. - */ - public int getMonth() { - return date.getMonthValue(); - } - - /** - * @return the day (of the month) field value. - */ - public int getDay() { - return date.getDayOfMonth(); - } - - /** - * @return temporal difference between this date and the other date. - */ - @NotNull - public Interval minus(Date other) { - // inverse of 'until' - return Interval.period(other.date.until(this.date)); - } - - /** - * @return a new Date representing the result of adding the interval to this Date - */ - @NotNull - public Date plus(Interval interval) { - LocalDate date; - if (interval instanceof Interval.YM) { - date = this.date.plus(((Interval.YM) interval).toPeriod()); - } else { - date = this.date.plus(((Interval.DT) interval).toDuration()); - } - return new Date(date); - } - - /** - * @return a new Date representing the result of subtracting the interval to this Date - */ - @NotNull - public Date minus(Interval interval) { - LocalDate date; - if (interval instanceof Interval.YM) { - date = this.date.minus(((Interval.YM) interval).toPeriod()); - } else { - date = this.date.minus(((Interval.DT) interval).toDuration()); - } - return new Date(date); - } - - @Override - public int hashCode() { - return date.hashCode(); - } - - /** - * In SQL, datetime values are mutually comparable if they share the same fields. - *
- * - * @param obj the object to compare to - * @return true if the objects are equal, false otherwise - */ - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof Date)) - return false; - return date.equals(((Date) obj).date); - } - - /** - * @return the SQL string for this date. - */ - @Override - public String toString() { - return "DATE " + date.format(formatter); - } -} diff --git a/partiql-spi/src/main/java/org/partiql/spi/datetime/Interval.java b/partiql-spi/src/main/java/org/partiql/spi/datetime/Interval.java deleted file mode 100644 index ed4e8cf18..000000000 --- a/partiql-spi/src/main/java/org/partiql/spi/datetime/Interval.java +++ /dev/null @@ -1,216 +0,0 @@ -package org.partiql.spi.datetime; - -import org.jetbrains.annotations.NotNull; - -import java.time.Duration; -import java.time.Period; - -/** - * This class represents a PartiQL Interval value. SQL defines two "classes" of intervals: year-month and day-time. - * In Java these are represented by {@link Period} and {@link Duration} respectively. - */ -public interface Interval { - - /** - * A {@link Period} based interval for the year-month interval class. - */ - public class YM implements Interval { - - /** - * The interval year, month, day (calendar aware). - */ - private final Period period; - - /** - * @param period a year-month INTERVAL part. - */ - private YM(@NotNull Period period) { - this.period = period; - } - - /** - * @return this interval as a Period. - */ - @NotNull - public Period toPeriod() { - return period; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof YM)) - return false; - return period.equals(((YM) obj).period); - } - - @Override - public int hashCode() { - return period.hashCode(); - } - - @Override - public String toString() { - return period.toString(); - } - } - - /** - * A {@link Duration} based interval for the day-time interval class. - */ - public class DT implements Interval { - - /** - * The seconds, nanoseconds of the interval (calendar unaware). - */ - @NotNull - private final Duration duration; - - /** - * @param duration a day-time INTERVAL part. - */ - private DT(@NotNull Duration duration) { - this.duration = duration; - } - - - /** - * @return this interval as a Duration. - */ - @NotNull - public Duration toDuration() { - return duration; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof DT)) - return false; - return duration.equals(((DT) obj).duration); - } - - @Override - public int hashCode() { - return duration.hashCode(); - } - - @Override - public String toString() { - return duration.toString(); - } - } - - @NotNull - public static YM period(Period period) { - return new YM(period); - } - - @NotNull - public static DT duration(Duration duration) { - return new DT(duration); - } - - /** - * Create an interval based on the number of years. - * - * @param years number of years - * @return new Interval - */ - @NotNull - public static YM years(int years) { - return new YM(Period.ofYears(years)); - } - - /** - * Create an interval based on the number of months. - * - * @param months number of months - * @return new Interval - */ - @NotNull - public static YM months(int months) { - return new YM(Period.ofMonths(months)); - } - - /** - * Create an interval based on the number of weeks. - * - * @param weeks number of weeks - * @return new Interval - */ - @NotNull - public static YM weeks(int weeks) { - return new YM(Period.ofWeeks(weeks)); - } - - /** - * Create an interval based on the number of days. - * - * @param days number of days - * @return new Interval - */ - @NotNull - public static YM days(int days) { - return new YM(Period.ofDays(days)); - } - - /** - * Create an interval based on the number of hours. - * - * @param hours number of hours - * @return new Interval - */ - @NotNull - public static DT hours(int hours) { - return new DT(Duration.ofHours(hours)); - } - - /** - * Create an interval based on the number of minutes. - * - * @param minutes number of minutes - * @return new Interval - */ - @NotNull - public static DT minutes(int minutes) { - return new DT(Duration.ofMinutes(minutes)); - } - - /** - * Create an interval based on the number of seconds. - * - * @param seconds number of seconds - * @return new Interval - */ - @NotNull - public static DT seconds(long seconds) { - return new DT(Duration.ofSeconds(seconds)); - } - - /** - * Create an interval based on the number milliseconds. - * @param milliseconds number of milliseconds - * @return new Interval - */ - @NotNull - public static DT millis(long milliseconds) { - return new DT(Duration.ofMillis(milliseconds)); - } - - /** - * Create an interval based on the number nanoseconds. - * @param nanoseconds number of nanoseconds - * @return new Interval - */ - @NotNull - public static DT nanos(long nanoseconds) { - return new DT(Duration.ofNanos(nanoseconds)); - } -} diff --git a/partiql-spi/src/main/java/org/partiql/spi/datetime/Time.java b/partiql-spi/src/main/java/org/partiql/spi/datetime/Time.java deleted file mode 100644 index ce7bd5776..000000000 --- a/partiql-spi/src/main/java/org/partiql/spi/datetime/Time.java +++ /dev/null @@ -1,150 +0,0 @@ -package org.partiql.spi.datetime; - -import org.jetbrains.annotations.NotNull; - -import java.time.LocalTime; - -/** - * A PartiQL time without timezone. - *
- * Usage - *
- *     Time.of(time); // time instanceof java.time.LocalTime
- *     Time.of(10, 30);
- *     Time.of(10, 30, 0);
- * 
- */ -public class Time { - - /** - * Delegate all functionality to {@link LocalTime}. - */ - @NotNull - private final LocalTime time; - - /** - * NO PUBLIC CONSTRUCTORS. - */ - private Time(@NotNull LocalTime time) { - this.time = time; - } - - /** - * @return time for current date-time for the system clock. - */ - @NotNull - public static Time now() { - return new Time(LocalTime.now()); - } - - /** - * Create a Time from a {@link LocalTime}. - * - * @param time local time (without timezone). - * @return new Time - */ - @NotNull - public static Time of(@NotNull LocalTime time) { - return new Time(time); - } - - /** - * Create a Time from an hour, minute. - * - * @param hour hour-of-day from 0 to 23 - * @param minute minute-of-hour from 0 to 59 - * @return new Time - */ - - @NotNull - public static Time of(int hour, int minute) { - return new Time(LocalTime.of(hour, minute)); - } - - /** - * Create a Time from an hour, minute, second. - * - * @param hour hour-of-day from 0 to 23 - * @param minute minute-of-hour from 0 to 59 - * @param second second-of-minute from 0 to 59 - * @return new Time - */ - @NotNull - public static Time of(int hour, int minute, int second) { - return new Time(LocalTime.of(hour, minute, second)); - } - - /** - * - * @param hour hour-of-day from 0 to 23 - * @param minute minute-of-hour from 0 to 59 - * @param second second-of-minute from 0 to 59 - * @param nano nano-of-second from 0 to 999,999,999 - * @return new Time - */ - @NotNull - public static Time of(int hour, int minute, int second, int nano) { - return new Time(LocalTime.of(hour, minute, second, nano)); - } - - /** - * @return a {@link LocalTime} for all functionality. - */ - @NotNull - public LocalTime toLocalTime() { - return time; - } - - /** - * @return the hour-of-day, from 0 to 23 - */ - public int getHour() { - return time.getHour(); - } - - /** - * @return the minute-of-hour, from 0 to 59 - */ - public int getMinute() { - return time.getMinute(); - } - - /** - * @return the second-of-minute, from 0 to 59 - */ - public int getSecond() { - return time.getSecond(); - } - - /** - * @return the nano-of-second, from 0 to 999,999,999 - */ - public int getNano() { - return time.getNano(); - } - - @Override - public int hashCode() { - return time.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof Time)) - return false; - return time.equals(((Time) obj).time); - } - - /** - * @return SQL string. - */ - @Override - public String toString() { - // TODO confirm SQL FORMATTER - return "TIME '" + time; - } -} diff --git a/partiql-spi/src/main/java/org/partiql/spi/datetime/Timestamp.java b/partiql-spi/src/main/java/org/partiql/spi/datetime/Timestamp.java deleted file mode 100644 index dfe639164..000000000 --- a/partiql-spi/src/main/java/org/partiql/spi/datetime/Timestamp.java +++ /dev/null @@ -1,182 +0,0 @@ -package org.partiql.spi.datetime; - - -import org.jetbrains.annotations.NotNull; - -import java.time.LocalDateTime; - -/** - * A PartiQL timestamp without timezone. - */ -public class Timestamp { - - private final Date date; - private final Time time; - - /** - * NO PUBLIC CONSTRUCTORS. - */ - private Timestamp(@NotNull Date date, @NotNull Time time) { - this.date = date; - this.time = time; - } - - /** - * @return timestamp for current date-time for the system clock. - */ - @NotNull - public Timestamp now() { - return new Timestamp(Date.now(), Time.now()); - } - - /** - * Create a new Timestamp from the date-time pair. - * - * @param date a date. - * @param time a time. - * @return new Timestamp - */ - @NotNull - public static Timestamp of(@NotNull Date date, @NotNull Time time) { - return new Timestamp(date, time); - } - - /** - * Create a new Timestamp from the fields. - * - * @param year the year to represent, from Year.MIN_YEAR to Year.MAX_YEAR - * @param month the month-of-year to represent, from 1 (January) to 12 (December) - * @param day the day of month to represent, from 1 to 31 - * @param hour hour-of-day from 0 to 23 - * @param minute minute-of-hour from 0 to 59 - * @param second second-of-minute from 0 to 59 - * @return new Timestamp - */ - @NotNull - public static Timestamp of(int year, int month, int day, int hour, int minute, int second) { - Date date = Date.of(year, month, day); - Time time = Time.of(hour, minute, second); - return new Timestamp(date, time); - } - - /** - * @param year the year to represent, from Year.MIN_YEAR to Year.MAX_YEAR - * @param month the month-of-year to represent, from 1 (January) to 12 (December) - * @param day the day of month to represent, from 1 to 31 - * @param hour hour-of-day from 0 to 23 - * @param minute minute-of-hour from 0 to 59 - * @param second second-of-minute from 0 to 59 - * @param nano nano-of-second from 0 to 999,999,999 - * @return new Timestamp - */ - @NotNull - public static Timestamp of(int year, int month, int day, int hour, int minute, int second, int nano) { - Date date = Date.of(year, month, day); - Time time = Time.of(hour, minute, second, nano); - return new Timestamp(date, time); - } - - /** - * Create a Timestamp from a {@link LocalDateTime}. - * - * @param timestamp local date time (without timezone). - * @return new Timestamp - */ - @NotNull - public static Timestamp of(@NotNull LocalDateTime timestamp) { - return new Timestamp(Date.of(timestamp.toLocalDate()), Time.of(timestamp.toLocalTime())); - } - - /** - * @return a {@link LocalDateTime} for this timestamp. - */ - @NotNull - public LocalDateTime toLocalDateTime() { - return LocalDateTime.of(date.toLocalDate(), time.toLocalTime()); - } - - /** - * @return the timestamp date. - */ - @NotNull - public Date toDate() { - return date; - } - - /** - * @return the timestamp time. - */ - @NotNull - public Time toTime() { - return time; - } - - /** - * @return the year of this date - */ - public int getYear() { - return date.getYear(); - } - - /** - * @return the month (of the year) field. - */ - public int getMonth() { - return date.getMonth(); - } - - /** - * @return the day-of-month field. - */ - public int getDay() { - return date.getDay(); - } - - /** - * @return the hour-of-day, from 0 to 23 - */ - public int getHour() { - return time.getHour(); - } - - /** - * @return the minute-of-hour, from 0 to 59 - */ - public int getMinute() { - return time.getMinute(); - } - - /** - * @return the second-of-minute, from 0 to 59 - */ - public int getSecond() { - return time.getSecond(); - } - - /** - * @return the nano-of-second, from 0 to 999,999,999 - */ - public int getNano() { - return time.getNano(); - } - - @Override - public int hashCode() { - return toLocalDateTime().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Timestamp)) return false; - Timestamp o = (Timestamp) obj; - return time.equals(o.time) && date.equals(o.date); - } - - @Override - public String toString() { - // TODO confirm SQL format - return "TIMESTAMP " + date + " " + time; - } -} diff --git a/partiql-spi/src/main/java/org/partiql/spi/datetime/Timestampz.java b/partiql-spi/src/main/java/org/partiql/spi/datetime/Timestampz.java deleted file mode 100644 index e208f3e6c..000000000 --- a/partiql-spi/src/main/java/org/partiql/spi/datetime/Timestampz.java +++ /dev/null @@ -1,163 +0,0 @@ -package org.partiql.spi.datetime; - - -import org.jetbrains.annotations.NotNull; - -import java.time.LocalDateTime; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; - -/** - * A PartiQL timestamp without timezone. - */ -public class Timestampz { - - private final Date date; - private final Timez time; - - /** - * NO PUBLIC CONSTRUCTORS. - */ - private Timestampz(@NotNull Date date, @NotNull Timez time) { - this.date = date; - this.time = time; - } - - /** - * @return timestamp for current date-time for the system clock. - */ - @NotNull - public Timestampz now() { - return new Timestampz(Date.now(), Timez.now()); - } - - /** - * Create a new Timestampz from the date-time pair. - * - * @param date a date. - * @param time a time. - * @return new Timestampz - */ - @NotNull - public static Timestampz of(@NotNull Date date, @NotNull Timez time) { - return new Timestampz(date, time); - } - - /** - * Create a Timestampz from a {@link LocalDateTime}. - * - * @param timestamp local date time (without timezone). - * @return new Timestampz - */ - @NotNull - public static Timestampz of(@NotNull OffsetDateTime timestamp) { - return new Timestampz(Date.of(timestamp.toLocalDate()), Timez.of(timestamp.toOffsetTime())); - } - - /** - * @return a {@link LocalDateTime}. - */ - @NotNull - public LocalDateTime toLocalDateTime() { - return LocalDateTime.of(date.toLocalDate(), time.toLocalTime()); - } - - /** - * @return an {@link OffsetDateTime}. - */ - @NotNull - public OffsetDateTime toOffsetDateTime() { - return OffsetDateTime.of(toLocalDateTime(), time.getOffset()); - } - - /** - * @return the timestamp date. - */ - @NotNull - public Date toDate() { - return date; - } - - /** - * @return the timestamp time. - */ - @NotNull - public Timez toTimez() { - return time; - } - - /** - * @return the year of this date - */ - public int getYear() { - return date.getYear(); - } - - /** - * @return the month (of the year) field. - */ - public int getMonth() { - return date.getMonth(); - } - - /** - * @return the day-of-month field. - */ - public int getDay() { - return date.getDay(); - } - - /** - * @return the hour-of-day, from 0 to 23 - */ - public int getHour() { - return time.getHour(); - } - - /** - * @return the minute-of-hour, from 0 to 59 - */ - public int getMinute() { - return time.getMinute(); - } - - /** - * @return the second-of-minute, from 0 to 59 - */ - public int getSecond() { - return time.getSecond(); - } - - /** - * @return the nano-of-second, from 0 to 999,999,999 - */ - public int getNano() { - return time.getNano(); - } - - - @NotNull - public ZoneOffset getOffset() { - return time.getOffset(); - } - - @Override - public int hashCode() { - return toLocalDateTime().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Timestampz)) return false; - Timestampz o = (Timestampz) obj; - return time.equals(o.time) && date.equals(o.date); - } - - @Override - public String toString() { - // TODO confirm SQL format - return "TIMESTAMPZ " + date + " " + time; - } -} diff --git a/partiql-spi/src/main/java/org/partiql/spi/datetime/Timez.java b/partiql-spi/src/main/java/org/partiql/spi/datetime/Timez.java deleted file mode 100644 index 6bd4a5b6c..000000000 --- a/partiql-spi/src/main/java/org/partiql/spi/datetime/Timez.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.partiql.spi.datetime; - -import jdk.vm.ci.meta.Local; -import org.jetbrains.annotations.NotNull; - -import java.time.LocalTime; -import java.time.OffsetTime; -import java.time.ZoneOffset; - -/** - * A PartiQL time with a UTC-offset timezone. - *
- * Usage - *
- *     Timez.of(time); // time instanceof java.time.OffsetTime
- *     Timez.of(10, 30);
- *     Timez.of(10, 30, 0);
- * 
- */ -public class Timez { - - /** - * Delegate all functionality to {@link OffsetTime}. - */ - @NotNull - private final OffsetTime time; - - /** - * NO PUBLIC CONSTRUCTORS. - */ - private Timez(@NotNull OffsetTime time) { - this.time = time; - } - - /** - * @return timez for current date-time for the system clock. - */ - @NotNull - public static Timez now() { - return new Timez(OffsetTime.now()); - } - - /** - * Create a Timez from a {@link OffsetTime}. - * - * @param time offset time (with timezone). - * @return new Timez - */ - @NotNull - public static Timez of(@NotNull OffsetTime time) { - return new Timez(time); - } - - /** - * Create a Timez from a {@link LocalTime} and {@link ZoneOffset}. - * - * @param time local time (without timezone). - * @param offset timezone offset - * @return new Timez - */ - @NotNull - public static Timez of(@NotNull LocalTime time, @NotNull ZoneOffset offset) { - return new Timez(OffsetTime.of(time, offset)); - } - - /** - * @return a {@link LocalTime} - */ - @NotNull - public LocalTime toLocalTime() { - return time.toLocalTime(); - } - - /** - * @return an {@link OffsetTime} - */ - @NotNull - public OffsetTime toOffsetTime() { - return time; - } - - /** - * @return the hour-of-day, from 0 to 23 - */ - public int getHour() { - return time.getHour(); - } - - /** - * @return the minute-of-hour, from 0 to 59 - */ - public int getMinute() { - return time.getMinute(); - } - - /** - * @return the second-of-minute, from 0 to 59 - */ - public int getSecond() { - return time.getSecond(); - } - - /** - * @return the nano-of-second, from 0 to 999,999,999 - */ - public int getNano() { - return time.getNano(); - } - - @NotNull - public ZoneOffset getOffset() { - return time.getOffset(); - } - - @Override - public int hashCode() { - return time.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof Timez)) - return false; - return time.equals(((Timez) obj).time); - } - - /** - * @return SQL string. - */ - @Override - public String toString() { - // TODO confirm SQL FORMATTER - return "TIMEZ '" + time; - } -} diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/Datum.java b/partiql-spi/src/main/java/org/partiql/spi/value/Datum.java index e35dbdbae..99acabdad 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/Datum.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/Datum.java @@ -6,7 +6,6 @@ import org.jetbrains.annotations.Nullable; import org.partiql.errors.DataException; import org.partiql.types.PType; -import org.partiql.value.DecimalValue; import org.partiql.value.PartiQL; import org.partiql.value.PartiQLValue; import org.partiql.value.PartiQLValueType; @@ -19,6 +18,7 @@ import java.math.MathContext; import java.math.RoundingMode; import java.nio.charset.Charset; +import java.time.*; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; @@ -143,61 +143,57 @@ default byte getByte() { } /** - * @return the underlying value applicable to the types: - * {@link PartiQLValueType#DATE}. - * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method - * will throw this exception upon invocation. - * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that - * {@link #isNull()} returns false before attempting to invoke this method. + * @return a {@link LocalDate} for DATE, TIMESTAMP, and TIMESTAMPZ types. + * + * @throws UnsupportedOperationException if type not in (DATE, TIMESTAMP, TIMESTAMPZ) + * @throws NullPointerException if isNull() is true; callers should check to avoid NPEs. */ @NotNull - default org.partiql.value.datetime.Date getDate() { + default LocalDate getLocalDate() { throw new UnsupportedOperationException(); } /** - * @return the underlying value applicable to the types: - * {@link PartiQLValueType#TIME} - * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method - * will throw this exception upon invocation. - * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that - * {@link #isNull()} returns false before attempting to invoke this method. + * @return an {@link OffsetTime} for TIME and TIMESTAMP types. + * + * @throws UnsupportedOperationException if type not in (TIME, TIMESTAMP) + * @throws NullPointerException if isNull() is true; callers should check to avoid NPEs. */ @NotNull - default Time getTime() { + default LocalTime getLocalTime() { throw new UnsupportedOperationException(); } /** - * @return the underlying value applicable to the types: - * {@link PartiQLValueType#TIMESTAMP}. - * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method - * will throw this exception upon invocation. - * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that - * {@link #isNull()} returns false before attempting to invoke this method. + * @return an {@link OffsetTime} for TIMEZ and TIMESTAMPZ types. + * + * @throws UnsupportedOperationException if type not in (TIMEZ, TIMESTAMPZ) + * @throws NullPointerException if isNull() is true; callers should check to avoid NPEs. + */ + @NotNull + default OffsetTime getOffsetTime() { + throw new UnsupportedOperationException("Cannot call getOffsetTime "); + } + + /** + * @return a {@link Period} for the INTERVALYM type. + * + * @throws UnsupportedOperationException if type not in [INTERVAL] + * @throws NullPointerException if isNull() is true; callers should check to avoid NPEs. */ @NotNull - default Timestamp getTimestamp() { + default Period getPeriod() { throw new UnsupportedOperationException(); } /** - * ! ! ! EXPERIMENTAL ! ! ! This is an experimental API under development by the PartiQL maintainers. - * @return the underlying value applicable to the types: - * {@link PartiQLValueType#INTERVAL}. - * @throws UnsupportedOperationException if the operation is not applicable to the type returned from - * {@link #getType()}; for example, if {@link #getType()} returns a {@link PartiQLValueType#INT}, then this method - * will throw this exception upon invocation. - * @throws NullPointerException if this instance also returns true on {@link #isNull()}; callers should check that - * {@link #isNull()} returns false before attempting to invoke this method. - * Please abstain from using this API until given notice otherwise. This may break between iterations without prior notice. - * @deprecated This implementation is likely wrong and is not recommended for use. + * @return a {@link Duration} for the INTERVALDT type. + * + * @throws UnsupportedOperationException if type not in [INTERVALDT] + * @throws NullPointerException if isNull() is true; callers should check to avoid NPEs. */ - @Deprecated - default long getInterval() { + @NotNull + default Duration getDuration() { throw new UnsupportedOperationException(); } @@ -712,21 +708,41 @@ static Datum blob(@NotNull byte[] value, int length) { return new DatumBytes(value, PType.blob(length)); } - // DATE/TIME + // DATE/TIME & INTERVAL @NotNull - static Datum date(@NotNull Date value) { + static Datum date(@NotNull LocalDate value) { return new DatumDate(value); } @NotNull - static Datum time(@NotNull Time value) { - return new DatumTime(value); + static Datum time(@NotNull LocalTime value, int precision) { + return new DatumTime(value, precision); + } + + @NotNull + static Datum timez(@NotNull OffsetTime value, int precision) { + return new DatumTimez(value, precision); + } + + @NotNull + static Datum timestamp(@NotNull LocalDateTime value, int precision) { + return new DatumTimestamp(value, precision); + } + + @NotNull + static Datum timestampz(@NotNull OffsetDateTime value, int precision) { + return new DatumTimestampz(value, precision); + } + + @NotNull + static Datum interval(@NotNull Period value, int precision) { + return new DatumIntervalYM(value, precision); } @NotNull - static Datum timestamp(@NotNull Timestamp value) { - return new DatumTimestamp(value); + static Datum interval(@NotNull Duration value, int precision) { + return new DatumIntervalDT(value, precision); } // COLLECTIONS diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumDate.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumDate.java index cac1a359a..d8c1dce6e 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumDate.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumDate.java @@ -3,34 +3,33 @@ import org.jetbrains.annotations.NotNull; import org.partiql.types.PType; +import java.time.LocalDate; + /** - * This shall always be package-private (internal). + * Today we wrap a {@link LocalDate}, in the future we can do a 7-byte array to avoid double references. */ -class DatumDate implements Datum { +final class DatumDate implements Datum { @NotNull - private final org.partiql.value.datetime.Date _value; + private final PType type; - private static final PType _type = PType.date(); + @NotNull + private final LocalDate value; - DatumDate(@NotNull org.partiql.value.datetime.Date value) { - _value = value; + DatumDate(@NotNull LocalDate value) { + this.type = PType.date(); + this.value = value; } + @NotNull @Override - public boolean isNull() { - return false; + public PType getType() { + return type; } @Override @NotNull - public org.partiql.value.datetime.Date getDate() { - return _value; - } - - @NotNull - @Override - public PType getType() { - return _type; + public LocalDate getLocalDate() { + return value; } } diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumInterval.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumInterval.java deleted file mode 100644 index 4fd9f2b45..000000000 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumInterval.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.partiql.spi.value; - -import org.jetbrains.annotations.NotNull; -import org.partiql.types.PType; - -/** - * This shall always be package-private (internal). - */ -class DatumInterval implements Datum { - - private final long _value; - - DatumInterval(long value) { - _value = value; - } - - @Override - public long getInterval() { - return _value; - } - - @NotNull - @Override - public PType getType() { - throw new UnsupportedOperationException("NOT YET IMPLEMENTED"); - } -} diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumIntervalDT.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumIntervalDT.java new file mode 100644 index 000000000..e70e4798e --- /dev/null +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumIntervalDT.java @@ -0,0 +1,30 @@ +package org.partiql.spi.value; + +import org.jetbrains.annotations.NotNull; +import org.partiql.types.PType; + +import java.time.Duration; + +/** + * Today we wrap a {@link Duration}, in the future we can do an 11 byte array. + */ +final class DatumIntervalDT implements Datum { + + @NotNull + private final Duration value; + + DatumIntervalDT(@NotNull Duration value, int precision) { + throw new UnsupportedOperationException("INTERVAL_DT not supported"); + } + + @NotNull + public PType getType() { + throw new UnsupportedOperationException("INTERVAL_DT not supported"); + } + + @NotNull + @Override + public Duration getDuration() { + return value; + } +} diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumIntervalYM.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumIntervalYM.java new file mode 100644 index 000000000..b98376407 --- /dev/null +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumIntervalYM.java @@ -0,0 +1,30 @@ +package org.partiql.spi.value; + +import org.jetbrains.annotations.NotNull; +import org.partiql.types.PType; + +import java.time.Period; + +/** + * Today we wrap a {@link Period}, in the future we can do an 11 byte array. + */ +final class DatumIntervalYM implements Datum { + + @NotNull + private final Period value; + + DatumIntervalYM(@NotNull Period value, int precision) { + throw new UnsupportedOperationException("INTERVAL_YM not supported"); + } + + @NotNull + public PType getType() { + throw new UnsupportedOperationException("INTERVAL_YM not supported"); + } + + @NotNull + @Override + public Period getPeriod() { + return value; + } +} diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumNull.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumNull.java index b6a773e1e..0577ba597 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumNull.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumNull.java @@ -8,6 +8,7 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.time.*; import java.util.Iterator; /** @@ -112,16 +113,6 @@ public byte[] getBytes() { } } - @NotNull - @Override - public Date getDate() { - if (_type.getKind() == PType.Kind.DATE) { - throw new NullPointerException(); - } else { - throw new UnsupportedOperationException(); - } - } - @Override public double getDouble() { if (_type.getKind() == PType.Kind.DOUBLE) { @@ -172,26 +163,63 @@ public String getString() { @NotNull @Override - public Time getTime() { - if (_type.getKind() == PType.Kind.TIMEZ || _type.getKind() == PType.Kind.TIME) { - throw new NullPointerException(); - } else { - throw new UnsupportedOperationException(); + public LocalDate getLocalDate() { + switch (_type.getKind()) { + case DATE: + case TIMESTAMP: + case TIMESTAMPZ: + throw new NullPointerException(); + default: + throw new UnsupportedOperationException(); } } @NotNull @Override - public Timestamp getTimestamp() { - if (_type.getKind() == PType.Kind.TIMESTAMPZ || _type.getKind() == PType.Kind.TIMESTAMP) { - throw new NullPointerException(); - } else { - throw new UnsupportedOperationException(); + public LocalTime getLocalTime() { + switch (_type.getKind()) { + case TIME: + case TIMESTAMP: + throw new NullPointerException(); + default: + throw new UnsupportedOperationException(); } } + @NotNull + @Override + public OffsetTime getOffsetTime() { + PType.Kind kind = _type.getKind(); + switch (kind) { + case TIMEZ: + case TIMESTAMPZ: + throw new NullPointerException(); + default: + throw new UnsupportedOperationException(); + } + } + + @NotNull @Override - public long getInterval() { - throw new UnsupportedOperationException(); + public Duration getDuration() { + switch (_type.getKind()) { + // TODO INTERVAL_DT + // case INTERVAL_DT: + // throw new NullPointerException(); + default: + throw new UnsupportedOperationException(); + } + } + + @NotNull + @Override + public Period getPeriod() { + switch (_type.getKind()) { + // TODO INTERVAL_YM + // case INTERVAL_YM: + // throw new NullPointerException(); + default: + throw new UnsupportedOperationException(); + } } } diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumTime.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumTime.java index 1a2391e66..6d73ae325 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumTime.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumTime.java @@ -2,33 +2,34 @@ import org.jetbrains.annotations.NotNull; import org.partiql.types.PType; -import org.partiql.value.datetime.Time; + +import java.time.LocalTime; /** - * This shall always be package-private (internal). + * Today we wrap a {@link LocalTime}, in the future we do a 4-byte array to avoid double references. */ -class DatumTime implements Datum { +final class DatumTime implements Datum { @NotNull - private final Time _value; + private final PType type; - // TODO: Pass precision to constructor. - // TODO: Create a variant specifically for without TZ - private final static PType _type = PType.timez(6); + @NotNull + private final LocalTime value; - DatumTime(@NotNull Time value) { - _value = value; + DatumTime(@NotNull LocalTime value, int precision) { + this.type = PType.time(precision); + this.value = value; } - @Override @NotNull - public Time getTime() { - return _value; + @Override + public PType getType() { + return type; } @NotNull @Override - public PType getType() { - return _type; + public LocalTime getLocalTime() { + return value; } } diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimestamp.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimestamp.java index bc72fa684..0d9e77168 100644 --- a/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimestamp.java +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimestamp.java @@ -1,34 +1,44 @@ package org.partiql.spi.value; + import org.jetbrains.annotations.NotNull; import org.partiql.types.PType; -import org.partiql.value.datetime.Timestamp; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; /** - * This shall always be package-private (internal). + * Today we wrap a {@link LocalDateTime}, in the future we do a 7-byte array to avoid double references. */ -class DatumTimestamp implements Datum { +final class DatumTimestamp implements Datum { @NotNull - private final Timestamp _value; + private final PType type; - // TODO: Pass precision to constructor. - // TODO: Create a variant specifically for without TZ - private final static PType _type = PType.timestampz(6); + @NotNull + private final LocalDateTime value; - DatumTimestamp(@NotNull Timestamp value) { - _value = value; + DatumTimestamp(@NotNull LocalDateTime value, int precision) { + this.type = PType.timestamp(precision); + this.value = value; } + @NotNull @Override + public PType getType() { + return type; + } + @NotNull - public Timestamp getTimestamp() { - return _value; + @Override + public LocalDate getLocalDate() { + return value.toLocalDate(); } @NotNull @Override - public PType getType() { - return _type; + public LocalTime getLocalTime() { + return value.toLocalTime(); } } diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimestampz.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimestampz.java new file mode 100644 index 000000000..833c2733c --- /dev/null +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimestampz.java @@ -0,0 +1,44 @@ +package org.partiql.spi.value; + + +import org.jetbrains.annotations.NotNull; +import org.partiql.types.PType; + +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.time.OffsetTime; + +/** + * Today we wrap an {@link OffsetDateTime}, in the future we do an 8-byte array to avoid double references. + */ +final class DatumTimestampz implements Datum { + + @NotNull + private final PType type; + + @NotNull + private final OffsetDateTime value; + + DatumTimestampz(@NotNull OffsetDateTime value, int precision) { + this.type = PType.timestamp(precision); + this.value = value; + } + + @NotNull + @Override + public PType getType() { + return type; + } + + @NotNull + @Override + public LocalDate getLocalDate() { + return value.toLocalDate(); + } + + @NotNull + @Override + public OffsetTime getOffsetTime() { + return value.toOffsetTime(); + } +} diff --git a/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimez.java b/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimez.java new file mode 100644 index 000000000..ced3da88a --- /dev/null +++ b/partiql-spi/src/main/java/org/partiql/spi/value/DatumTimez.java @@ -0,0 +1,35 @@ +package org.partiql.spi.value; + +import org.jetbrains.annotations.NotNull; +import org.partiql.types.PType; + +import java.time.OffsetTime; + +/** + * Today we wrap an {@link OffsetTime}, in the future we do a 5-byte array to avoid double references. + */ +final class DatumTimez implements Datum { + + @NotNull + private final PType type; + + @NotNull + private final OffsetTime value; + + DatumTimez(@NotNull OffsetTime value, int precision) { + this.type = PType.timez(precision); + this.value = value; + } + + @NotNull + @Override + public PType getType() { + return type; + } + + @NotNull + @Override + public OffsetTime getOffsetTime() { + return value; + } +}