diff --git a/partiql-spi/api/partiql-spi.api b/partiql-spi/api/partiql-spi.api
index 2492caeaf..19972abff 100644
--- a/partiql-spi/api/partiql-spi.api
+++ b/partiql-spi/api/partiql-spi.api
@@ -310,6 +310,124 @@ public final class org/partiql/spi/catalog/Table$DefaultImpls {
public static fun getSchema (Lorg/partiql/spi/catalog/Table;)Lorg/partiql/types/PType;
}
+public class org/partiql/spi/datetime/Date {
+ public fun equals (Ljava/lang/Object;)Z
+ public fun getDay ()I
+ public fun getMonth ()I
+ public fun getYear ()I
+ public fun hashCode ()I
+ public fun minus (Lorg/partiql/spi/datetime/Date;)Lorg/partiql/spi/datetime/Interval;
+ public fun minus (Lorg/partiql/spi/datetime/Interval;)Lorg/partiql/spi/datetime/Date;
+ public static fun now ()Lorg/partiql/spi/datetime/Date;
+ public static fun of (III)Lorg/partiql/spi/datetime/Date;
+ public static fun of (Ljava/time/LocalDate;)Lorg/partiql/spi/datetime/Date;
+ public fun plus (Lorg/partiql/spi/datetime/Interval;)Lorg/partiql/spi/datetime/Date;
+ public fun toLocalDate ()Ljava/time/LocalDate;
+ public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class org/partiql/spi/datetime/Interval {
+ public static fun days (I)Lorg/partiql/spi/datetime/Interval$YM;
+ public static fun duration (Ljava/time/Duration;)Lorg/partiql/spi/datetime/Interval$DT;
+ public static fun hours (I)Lorg/partiql/spi/datetime/Interval$DT;
+ public static fun millis (J)Lorg/partiql/spi/datetime/Interval$DT;
+ public static fun minutes (I)Lorg/partiql/spi/datetime/Interval$DT;
+ public static fun months (I)Lorg/partiql/spi/datetime/Interval$YM;
+ public static fun nanos (J)Lorg/partiql/spi/datetime/Interval$DT;
+ public static fun period (Ljava/time/Period;)Lorg/partiql/spi/datetime/Interval$YM;
+ public static fun seconds (J)Lorg/partiql/spi/datetime/Interval$DT;
+ public static fun weeks (I)Lorg/partiql/spi/datetime/Interval$YM;
+ public static fun years (I)Lorg/partiql/spi/datetime/Interval$YM;
+}
+
+public class org/partiql/spi/datetime/Interval$DT : org/partiql/spi/datetime/Interval {
+ public fun equals (Ljava/lang/Object;)Z
+ public fun hashCode ()I
+ public fun toDuration ()Ljava/time/Duration;
+ public fun toString ()Ljava/lang/String;
+}
+
+public class org/partiql/spi/datetime/Interval$YM : org/partiql/spi/datetime/Interval {
+ public fun equals (Ljava/lang/Object;)Z
+ public fun hashCode ()I
+ public fun toPeriod ()Ljava/time/Period;
+ public fun toString ()Ljava/lang/String;
+}
+
+public class org/partiql/spi/datetime/Time {
+ public fun equals (Ljava/lang/Object;)Z
+ public fun getHour ()I
+ public fun getMinute ()I
+ public fun getNano ()I
+ public fun getSecond ()I
+ public fun hashCode ()I
+ public static fun now ()Lorg/partiql/spi/datetime/Time;
+ public static fun of (II)Lorg/partiql/spi/datetime/Time;
+ public static fun of (III)Lorg/partiql/spi/datetime/Time;
+ public static fun of (IIII)Lorg/partiql/spi/datetime/Time;
+ public static fun of (Ljava/time/LocalTime;)Lorg/partiql/spi/datetime/Time;
+ public fun toLocalTime ()Ljava/time/LocalTime;
+ public fun toString ()Ljava/lang/String;
+}
+
+public class org/partiql/spi/datetime/Timestamp {
+ public fun equals (Ljava/lang/Object;)Z
+ public fun getDay ()I
+ public fun getHour ()I
+ public fun getMinute ()I
+ public fun getMonth ()I
+ public fun getNano ()I
+ public fun getSecond ()I
+ public fun getYear ()I
+ public fun hashCode ()I
+ public fun now ()Lorg/partiql/spi/datetime/Timestamp;
+ public static fun of (IIIIII)Lorg/partiql/spi/datetime/Timestamp;
+ public static fun of (IIIIIII)Lorg/partiql/spi/datetime/Timestamp;
+ public static fun of (Ljava/time/LocalDateTime;)Lorg/partiql/spi/datetime/Timestamp;
+ public static fun of (Lorg/partiql/spi/datetime/Date;Lorg/partiql/spi/datetime/Time;)Lorg/partiql/spi/datetime/Timestamp;
+ public fun toDate ()Lorg/partiql/spi/datetime/Date;
+ public fun toLocalDateTime ()Ljava/time/LocalDateTime;
+ public fun toString ()Ljava/lang/String;
+ public fun toTime ()Lorg/partiql/spi/datetime/Time;
+}
+
+public class org/partiql/spi/datetime/Timestampz {
+ public fun equals (Ljava/lang/Object;)Z
+ public fun getDay ()I
+ public fun getHour ()I
+ public fun getMinute ()I
+ public fun getMonth ()I
+ public fun getNano ()I
+ public fun getOffset ()Ljava/time/ZoneOffset;
+ public fun getSecond ()I
+ public fun getYear ()I
+ public fun hashCode ()I
+ public fun now ()Lorg/partiql/spi/datetime/Timestampz;
+ public static fun of (Ljava/time/OffsetDateTime;)Lorg/partiql/spi/datetime/Timestampz;
+ public static fun of (Lorg/partiql/spi/datetime/Date;Lorg/partiql/spi/datetime/Timez;)Lorg/partiql/spi/datetime/Timestampz;
+ public fun toDate ()Lorg/partiql/spi/datetime/Date;
+ public fun toLocalDateTime ()Ljava/time/LocalDateTime;
+ public fun toOffsetDateTime ()Ljava/time/OffsetDateTime;
+ public fun toString ()Ljava/lang/String;
+ public fun toTimez ()Lorg/partiql/spi/datetime/Timez;
+}
+
+public class org/partiql/spi/datetime/Timez {
+ public fun equals (Ljava/lang/Object;)Z
+ public fun getHour ()I
+ public fun getMinute ()I
+ public fun getNano ()I
+ public fun getOffset ()Ljava/time/ZoneOffset;
+ public fun getSecond ()I
+ public fun hashCode ()I
+ public static fun now ()Lorg/partiql/spi/datetime/Timez;
+ public static fun of (Ljava/time/LocalTime;Ljava/time/ZoneOffset;)Lorg/partiql/spi/datetime/Timez;
+ public static fun of (Ljava/time/OffsetTime;)Lorg/partiql/spi/datetime/Timez;
+ public fun toLocalTime ()Ljava/time/LocalTime;
+ public fun toOffsetTime ()Ljava/time/OffsetTime;
+ public fun toString ()Ljava/lang/String;
+}
+
public final class org/partiql/spi/errors/PError : org/partiql/spi/Enum {
public static final field ALWAYS_MISSING I
public static final field FEATURE_NOT_SUPPORTED I
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
new file mode 100644
index 000000000..3e4cf31ea
--- /dev/null
+++ b/partiql-spi/src/main/java/org/partiql/spi/datetime/Date.java
@@ -0,0 +1,166 @@
+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
new file mode 100644
index 000000000..ed4e8cf18
--- /dev/null
+++ b/partiql-spi/src/main/java/org/partiql/spi/datetime/Interval.java
@@ -0,0 +1,216 @@
+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
new file mode 100644
index 000000000..ce7bd5776
--- /dev/null
+++ b/partiql-spi/src/main/java/org/partiql/spi/datetime/Time.java
@@ -0,0 +1,150 @@
+package org.partiql.spi.datetime;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.time.LocalTime;
+
+/**
+ * A PartiQL time without timezone.
+ *
+ * Usage
+ *
+ */
+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/kotlin/org/partiql/spi/datetime/Date.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Date.kt
deleted file mode 100644
index f5edc45e8..000000000
--- a/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Date.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-package org.partiql.spi.datetime
-
-import org.partiql.spi.datetime.util.DatetimeComparisons
-import java.math.BigDecimal
-
-/**
- * Superclass for all implementations representing date value.
- * Date represents a calendar system, (i.e., 2023-06-01).
- * It does not include information on time or timezone, instead, it is meant to represent a specific date on calendar.
- * For example, 2022-11-25 (black friday in 2022).
- * The valid range are from 0001-01-01 to 9999-12-31
- * The [day] must be valid for the year and month, otherwise an exception will be thrown.
- */
-public sealed interface Date : Datetime, Comparable {
-
- public override val year: Int
- public override val month: Int
- public override val day: Int
-
- /**
- * Hour field for [Date] value is always null.
- */
- public override val hour: Int?
- get() = null
-
- /**
- * Minute field for [Date] value is always null.
- */
- public override val minute: Int?
- get() = null
-
- /**
- * Second field for [Date] value is always null.
- */
- public override val decimalSecond: BigDecimal?
- get() = null
-
- /**
- * Timezone field for [Date] value is always null.
- */
- public override val timeZone: Timezone?
- get() = null
-
- // Operation
- /**
- * Construct a [Timestamp] value by appending [time] to this [Date] value.
- */
- public fun atTime(time: Time): Timestamp
-
- /**
- * Returns a [Date] value with the specified number of days added.
- * The month and year fields may be changed as necessary to ensure the result remains valid.
- * [days] can be negative.
- */
- public fun plusDays(days: Long): Date
-
- /**
- * Returns a [Date] value with the specified number of months added.
- * The month and year fields may be changed as necessary to ensure the result remains valid.
- * [months] can be negative.
- */
- public fun plusMonths(months: Long): Date
-
- /**
- * Returns a [Date] value with the specified number of months added.
- * [years] can be negative.
- */
- public fun plusYears(years: Long): Date
-
- /**
- * Comparison method for [Date] value.
- *
- * Since [Date] value has no concept of time zone, they are compared as calendar date.
- */
- public override fun compareTo(other: Date): Int =
- DatetimeComparisons.compareTo(this, other)
-}
-
-/**
- * Superclass for all implementation representing date value
- */
-public abstract class DateImpl : Date, Comparable {
- public final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other?.javaClass != javaClass) return false
- other as DateImpl
- if (this.year != other.year) return false
- if (this.month != other.month) return false
- if (this.day != other.day) return false
- return true
- }
-
- public final override fun hashCode(): Int =
- year.hashCode() + month.hashCode() + day.hashCode()
-
- public final override fun toString(): String =
- "${this.javaClass.simpleName}(year=$year, month=$month, day=$day)"
-}
\ No newline at end of file
diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Datetime.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Datetime.kt
deleted file mode 100644
index e68e93a26..000000000
--- a/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Datetime.kt
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License").
- * You may not use this file except in compliance with the License.
- * A copy of the License is located at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * or in the "license" file accompanying this file. This file is distributed
- * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
- * express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package org.partiql.spi.datetime
-
-import java.math.BigDecimal
-
-/**
- * Superclass for all classes representing datetime values.
- */
-public sealed interface Datetime {
- /**
- * Year field of date time object
- */
- public val year: Int?
-
- /**
- * Month field of date time object
- */
- public val month: Int?
-
- /**
- * Day field of date time object
- */
- public val day: Int?
-
- /**
- * Hour field of date time object
- */
- public val hour: Int?
-
- /**
- * Minute field of date time object
- */
- public val minute: Int?
-
- /**
- * Second field of date time object.
- * This field includes second fraction.
- */
- public val decimalSecond: BigDecimal?
-
- /**
- * Time zone field of date time object. See [Timezone]
- */
- public val timeZone: Timezone?
-
- /**
- * Equals method.
- * Two [Datetime] values are considered equals if and only if all the fields are equals.
- */
- public override fun equals(other: Any?): Boolean
-
- public override fun hashCode(): Int
-
- public override fun toString(): String
-
- public companion object {
-
- /**
- * Create a timestamp value.
- *
- * If time zone is null, then the value created is timestamp without timezone.
- * Otherwise, a timestamp with timezone is created.
- *
- * @param year Proleptic Year
- * @param month Month of Year
- * @param day Day Of Month
- * @param hour Hour of Day
- * @param minute Minute of Hour
- * @param second Second, include any fraction second.
- * @param timeZone TimeZone offset, see [Timezone]
- */
- @JvmStatic
- @JvmOverloads
- public fun timestamp(
- year: Int,
- month: Int = 1,
- day: Int = 1,
- hour: Int = 0,
- minute: Int = 0,
- second: BigDecimal = BigDecimal.ZERO,
- timeZone: Timezone? = null,
- ): Timestamp = when (timeZone) {
- Timezone.UnknownTimeZone -> {
- if (second.scale() <= 9) {
- OffsetTimestampLowPrecision.of(year, month, day, hour, minute, second, timeZone)
- } else {
- OffsetTimestampHighPrecision.of(year, month, day, hour, minute, second, timeZone)
- }
- }
- is Timezone.UtcOffset -> {
- if (timeZone.totalOffsetMinutes.absoluteValue > JAVA_MAX_OFFSET) {
- OffsetTimestampHighPrecision.of(year, month, day, hour, minute, second, timeZone)
- } else if (second.scale() <= 9) {
- OffsetTimestampLowPrecision.of(year, month, day, hour, minute, second, timeZone)
- } else {
- OffsetTimestampHighPrecision.of(year, month, day, hour, minute, second, timeZone)
- }
- }
-
- null -> {
- if (second.scale() <= 9) LocalTimestampLowPrecision.of(year, month, day, hour, minute, second)
- else LocalTimestampHighPrecision.of(year, month, day, hour, minute, second)
- }
- }
-
- /**
- * Create a timestamp value.
- * The timestamp created will have precision 0 (no fractional second).
- *
- * @param year Proleptic Year
- * @param month Month of Year
- * @param day Day Of Month
- * @param hour Hour of Day
- * @param minute Minute of Hour
- * @param second whole Second.
- * @param timeZone TimeZone offset, see [Timezone]
- */
- @JvmStatic
- @JvmOverloads
- public fun timestamp(
- year: Int,
- month: Int,
- day: Int,
- hour: Int,
- minute: Int,
- second: Int,
- timeZone: Timezone? = null,
- ): Timestamp = timestamp(year, month, day, hour, minute, second.toBigDecimal(), timeZone)
-
- /**
- * Create a timestamp value.
- * If time is an instance of [TimeWithTimeZone], then the timestamp created will be [TimestampWithTimeZone],
- * Otherwise it will be a [TimestampWithoutTimeZone].
- *
- * @param date: Date. See [Date]
- * @param time: Time. See [Time]
- */
- @JvmStatic
- public fun timestamp(date: Date, time: Time): Timestamp = when (time) {
- is TimeWithTimeZone -> timestamp(
- date.year, date.month, date.day, time.hour, time.minute, time.decimalSecond, time.timeZone
- )
-
- is TimeWithoutTimeZone -> timestamp(
- date.year, date.month, date.day, time.hour, time.minute, time.decimalSecond
- )
- }
-
- /**
- * Create a timestamp value based on [com.amazon.ion.Timestamp]
- * The created timestamp will always be an instance of [TimestampWithTimeZone]
- */
- @JvmStatic
- public fun timestamp(ionTimestamp: com.amazon.ion.Timestamp): TimestampWithTimeZone =
- if (ionTimestamp.localOffset != null && ionTimestamp.localOffset.absoluteValue > JAVA_MAX_OFFSET) {
- OffsetTimestampHighPrecision.forIonTimestamp(ionTimestamp)
- } else if (ionTimestamp.decimalSecond.scale() <= 9) {
- OffsetTimestampLowPrecision.forIonTimestamp(ionTimestamp)
- } else {
- OffsetTimestampHighPrecision.forIonTimestamp(ionTimestamp)
- }
-
- /**
- * Create a timestamp value based on displacement of Unix Epoch, at given time zone.
- * The created timestamp will always be an instance of [TimestampWithTimeZone]
- */
- @JvmStatic
- public fun timestamp(epochSeconds: BigDecimal, timeZone: Timezone): TimestampWithTimeZone = when (timeZone) {
- Timezone.UnknownTimeZone -> {
- if (epochSeconds.scale() <= 9) {
- OffsetTimestampLowPrecision.forEpochSeconds(epochSeconds, timeZone)
- } else {
- OffsetTimestampHighPrecision.forEpochSeconds(epochSeconds, timeZone)
- }
- }
- is Timezone.UtcOffset -> {
- if (timeZone.totalOffsetMinutes > JAVA_MAX_OFFSET) {
- OffsetTimestampHighPrecision.forEpochSeconds(epochSeconds, timeZone)
- } else if (epochSeconds.scale() <= 9) {
- OffsetTimestampLowPrecision.forEpochSeconds(epochSeconds, timeZone)
- } else {
- OffsetTimestampHighPrecision.forEpochSeconds(epochSeconds, timeZone)
- }
- }
- }
-
- /**
- * Create a time value.
- *
- * If time zone is null, then the value created is time without timezone.
- * Otherwise, a time with timezone is created.
- *
- * @param hour Hour of Day
- * @param minute Minute of Hour
- * @param second Second, include any fraction second.
- * @param timeZone TimeZone offset, see [Timezone]
- */
- @JvmStatic
- @JvmOverloads
- public fun time(
- hour: Int,
- minute: Int,
- second: BigDecimal,
- timeZone: Timezone? = null,
- ): Time = when (timeZone) {
- Timezone.UnknownTimeZone -> {
- if (second.scale() <= 9) {
- OffsetTimeLowPrecision.of(hour, minute, second, timeZone)
- } else {
- OffsetTimeHighPrecision.of(hour, minute, second, timeZone)
- }
- }
- is Timezone.UtcOffset -> {
- if (timeZone.totalOffsetMinutes.absoluteValue > JAVA_MAX_OFFSET) {
- OffsetTimeHighPrecision.of(hour, minute, second, timeZone)
- } else if (second.scale() <= 9) {
- OffsetTimeLowPrecision.of(hour, minute, second, timeZone)
- } else {
- OffsetTimeHighPrecision.of(hour, minute, second, timeZone)
- }
- }
-
- null -> {
- if (second.scale() <= 9) LocalTimeLowPrecision.of(hour, minute, second)
- else LocalTimeHighPrecision.of(hour, minute, second)
- }
- }
-
- /**
- * Create a time value.
- * The time created will have precision 0 (no fractional second).
- *
- * @param hour Hour of Day
- * @param minute Minute of Hour
- * @param second whole Second.
- * @param timeZone TimeZone offset, see [Timezone]
- */
- @JvmStatic
- @JvmOverloads
- public fun time(
- hour: Int,
- minute: Int,
- second: Int,
- timeZone: Timezone? = null,
- ): Time = time(hour, minute, second.toBigDecimal(), timeZone)
-
- /**
- * Create a time value.
- * The time created will have precision 9 (nanosecond precision).
- *
- * @param hour Hour of Day
- * @param minute Minute of Hour
- * @param second whole Second.
- * @param nano Nano offset.
- * @param timeZone TimeZone offset, see [Timezone]
- */
- @JvmStatic
- @JvmOverloads
- public fun time(
- hour: Int,
- minute: Int,
- second: Int,
- nano: Int,
- timeZone: Timezone? = null,
- ): Time {
- val decimalSecond = second.toBigDecimal().plus(nano.toBigDecimal().movePointLeft(9))
- return time(hour, minute, decimalSecond, timeZone)
- }
-
- @JvmStatic
- public fun date(
- year: Int,
- month: Int,
- day: Int,
- ): Date = SqlDate.of(year, month, day)
- }
-}
-
diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Interval.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Interval.kt
deleted file mode 100644
index 431703495..000000000
--- a/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Interval.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.partiql.spi.datetime
-
-import java.math.BigDecimal
-
-/**
- * This is experimental and, at present, cannot be instantiated.
- *
- * An interval is composed of a contiguous subset of the fields.
- * The subset of the fields is called the “precision” of the value.
- * The leading field, either “YEAR” or “DAY” is only constrained by the “leading-field” precision.
- * All fields are integers except for “SECOND” which has “fractional seconds precision”.
- */
-public class Interval private constructor(
- private val years: Int,
- private val months: Int,
- private val days: Int,
- private val hours: Int,
- private val minutes: Int,
- private val seconds: BigDecimal
-) {
-
- /**
- * Years, range: unconstrained.
- */
- public fun getYears(): Int = 0
-
- /**
- * Months, range: [0,11]
- */
- public fun getMonths(): Int = 0
-
- /**
- * Days, range: unconstrained
- */
- public fun getDays(): Int = 0
-
- /**
- * Hours, range: [0,23]
- */
- public fun getHours(): Int = 0
-
- /**
- * Minutes, range: [0,59]
- */
- public fun getMinutes(): Int = 0
-
- /**
- * Seconds, range: [0,59.999999999...]
- *
- * NOTE: The BigDecimal value precision reflects the interval seconds precision.
- */
- public fun getSeconds(): BigDecimal = BigDecimal.ZERO
-}
diff --git a/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Time.kt b/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Time.kt
deleted file mode 100644
index c884ae0d0..000000000
--- a/partiql-spi/src/main/kotlin/org/partiql/spi/datetime/Time.kt
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.partiql.spi.datetime
-
-import org.partiql.spi.datetime.util.DatetimeComparisons
-import org.partiql.spi.datetime.util.DatetimePrecisionUtil
-import org.partiql.spi.datetime.util.DatetimeUtil.toBigDecimal
-import java.math.BigDecimal
-
-/**
- * Superclass for all implementations representing time value.
- * See [TimeWithTimeZone] and [TimeWithoutTimeZone]
- */
-public sealed interface Time : Datetime, Comparable