Skip to content

Commit 8c8cd92

Browse files
committed
Some fixes to time/timestamp with precision sorting
- fixes timestamp lowering - fixes optional subsecond handling
1 parent 11ab169 commit 8c8cd92

File tree

2 files changed

+29
-23
lines changed

2 files changed

+29
-23
lines changed

partiql-logical-planner/src/lower.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -849,9 +849,11 @@ impl<'ast> Visitor<'ast> for AstToLogical {
849849
Type::TimeTypeWithTimeZone(p) => {
850850
Value::DateTime(Box::new(DateTime::from_hh_mm_ss_time_zone(s, p)))
851851
}
852-
Type::TimestampType(p) => Value::DateTime(Box::new(DateTime::from_hh_mm_ss(s, p))),
852+
Type::TimestampType(p) => {
853+
Value::DateTime(Box::new(DateTime::from_yyyy_mm_dd_hh_mm_ss(s, p)))
854+
}
853855
Type::ZonedTimestampType(p) => {
854-
Value::DateTime(Box::new(DateTime::from_hh_mm_ss_time_zone(s, p)))
856+
Value::DateTime(Box::new(DateTime::from_yyyy_mm_dd_hh_mm_ss_time_zone(s, p)))
855857
}
856858
_ => todo!("Other types"),
857859
},

partiql-value/src/datetime.rs

+25-21
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::fmt::{Debug, Formatter};
55
use std::hash::Hash;
66
use std::num::NonZeroU8;
77
use time::macros::format_description;
8-
use time::{Duration, UtcOffset};
8+
use time::UtcOffset;
99

1010
#[derive(Hash, PartialEq, Eq, Clone)]
1111
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@@ -91,39 +91,42 @@ impl DateTime {
9191
}
9292

9393
pub fn from_yyyy_mm_dd(date: &str) -> Self {
94+
// TODO: for better error mesaging, perhaps could include in our parser or create separate
95+
// parser for these date, time, and timestamp strings
9496
let format = format_description!("[year]-[month]-[day]");
9597
let date = time::Date::parse(date, &format).expect("valid date string");
9698
DateTime::Date(date)
9799
}
98100

99101
pub fn from_hh_mm_ss(time: &str, precision: &Option<u32>) -> Self {
100-
let format = format_description!("[hour]:[minute]:[second].[subsecond]");
102+
let format = format_description!("[hour]:[minute]:[second][optional [.[subsecond]]]");
101103
let time = time::Time::parse(time, &format).expect("valid time string");
102104
DateTime::Time(time, *precision)
103105
}
104106

105107
pub fn from_hh_mm_ss_time_zone(time: &str, precision: &Option<u32>) -> Self {
106108
let time_format = format_description!(
107-
"[hour]:[minute]:[second].[subsecond][offset_hour]:[offset_minute]"
109+
"[hour]:[minute]:[second][optional [.[subsecond]]][offset_hour]:[offset_minute]"
108110
);
109111
let time_part = time::Time::parse(time, &time_format).expect("valid time with time zone");
110112
let time_format = format_description!(
111-
"[hour]:[minute]:[second].[subsecond][offset_hour]:[offset_minute]"
113+
"[hour]:[minute]:[second][optional [.[subsecond]]][offset_hour]:[offset_minute]"
112114
);
113115
let offset_part = time::UtcOffset::parse(time, &time_format).expect("valid time zone");
114116
DateTime::TimeWithTz(time_part, *precision, offset_part)
115117
}
116118

117119
pub fn from_yyyy_mm_dd_hh_mm_ss(timestamp: &str, precision: &Option<u32>) -> Self {
118-
let format =
119-
format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]");
120+
let format = format_description!(
121+
"[year]-[month]-[day] [hour]:[minute]:[second][optional [.[subsecond]]]"
122+
);
120123
let time =
121124
time::PrimitiveDateTime::parse(timestamp, &format).expect("valid timestamp string");
122125
DateTime::Timestamp(time, *precision)
123126
}
124127

125128
pub fn from_yyyy_mm_dd_hh_mm_ss_time_zone(timestamp: &str, precision: &Option<u32>) -> Self {
126-
let format = format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour]:[offset_minute]");
129+
let format = format_description!("[year]-[month]-[day] [hour]:[minute]:[second][optional [.[subsecond]]][offset_hour]:[offset_minute]");
127130
let time = time::OffsetDateTime::parse(timestamp, &format)
128131
.expect("valid timestamp string with time zone");
129132
DateTime::TimestampWithTz(time, *precision)
@@ -174,29 +177,30 @@ impl Ord for DateTime {
174177
(DateTime::Date(_), _) => Ordering::Less,
175178
(_, DateTime::Date(_)) => Ordering::Greater,
176179

177-
(DateTime::Time(l, _lp), DateTime::Time(r, _rp)) => l.cmp(r),
178-
// TODO: sorting using the time precisions
180+
// follow convention of timestamp mentioned in section 12.2 to ignore precision and local utc offset
181+
(DateTime::Time(l, _), DateTime::Time(r, _)) => l.cmp(r),
179182
(DateTime::Time(_, _), _) => Ordering::Less,
180183
(_, DateTime::Time(_, _)) => Ordering::Greater,
181184

182-
(DateTime::TimeWithTz(l, _lp, lo), DateTime::TimeWithTz(r, _rp, ro)) => {
183-
// TODO: sorting using the time precisions
184-
let lod = Duration::new(lo.whole_seconds() as i64, 0);
185-
let rod = Duration::new(ro.whole_seconds() as i64, 0);
186-
let l_adjusted = *l + lod;
187-
let r_adjusted = *r + rod;
188-
l_adjusted.cmp(&r_adjusted)
189-
}
185+
// follow convention of timestamp mentioned in section 12.2 to ignore precision and local utc offset
186+
(DateTime::TimeWithTz(l, _, _), DateTime::TimeWithTz(r, _, _)) => l.cmp(r),
190187
(DateTime::TimeWithTz(_, _, _), _) => Ordering::Less,
191188
(_, DateTime::TimeWithTz(_, _, _)) => Ordering::Greater,
192189

193-
// TODO: sorting using the timestamp precisions
194-
(DateTime::Timestamp(l, _lp), DateTime::Timestamp(r, _rp)) => l.cmp(r),
190+
// per section 12.2 of spec, timestamp values are compared irrespective of precision or local UTC offset
191+
(DateTime::Timestamp(l, _), DateTime::Timestamp(r, _)) => l.cmp(r),
195192
(DateTime::Timestamp(_, _), _) => Ordering::Less,
196193
(_, DateTime::Timestamp(_, _)) => Ordering::Greater,
197194

198-
// TODO: sorting using the timestamp precisions
199-
(DateTime::TimestampWithTz(l, _lp), DateTime::TimestampWithTz(r, _rp)) => l.cmp(r),
195+
// per section 12.2 of spec, timestamp values are compared irrespective of precision or local UTC offset
196+
(DateTime::TimestampWithTz(l, _), DateTime::TimestampWithTz(r, _)) => {
197+
let date_ord = l.date().cmp(&r.date());
198+
if date_ord != Ordering::Equal {
199+
date_ord
200+
} else {
201+
l.time().cmp(&r.time())
202+
}
203+
}
200204
}
201205
}
202206
}

0 commit comments

Comments
 (0)