Skip to content

Commit 8ae4d7e

Browse files
committed
expr: convert a few more date functions
Signed-off-by: Petros Angelatos <[email protected]>
1 parent 645f7cc commit 8ae4d7e

File tree

3 files changed

+195
-98
lines changed

3 files changed

+195
-98
lines changed

src/expr/src/scalar/func.rs

Lines changed: 32 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,43 +1877,11 @@ where
18771877
{
18781878
let units = a.unwrap_str();
18791879
match units.parse() {
1880-
Ok(units) => date_trunc_inner(units, ts),
1880+
Ok(units) => Ok(date_trunc_inner(units, ts)?.into()),
18811881
Err(_) => Err(EvalError::UnknownUnits(units.to_owned())),
18821882
}
18831883
}
18841884

1885-
fn date_trunc_inner<'a, T>(units: DateTimeUnits, ts: T) -> Result<Datum<'a>, EvalError>
1886-
where
1887-
T: TimestampLike,
1888-
{
1889-
match units {
1890-
DateTimeUnits::Millennium => Ok(ts.truncate_millennium().into()),
1891-
DateTimeUnits::Century => Ok(ts.truncate_century().into()),
1892-
DateTimeUnits::Decade => Ok(ts.truncate_decade().into()),
1893-
DateTimeUnits::Year => Ok(ts.truncate_year().into()),
1894-
DateTimeUnits::Quarter => Ok(ts.truncate_quarter().into()),
1895-
DateTimeUnits::Week => Ok(ts.truncate_week()?.into()),
1896-
DateTimeUnits::Day => Ok(ts.truncate_day().into()),
1897-
DateTimeUnits::Hour => Ok(ts.truncate_hour().into()),
1898-
DateTimeUnits::Minute => Ok(ts.truncate_minute().into()),
1899-
DateTimeUnits::Second => Ok(ts.truncate_second().into()),
1900-
DateTimeUnits::Month => Ok(ts.truncate_month().into()),
1901-
DateTimeUnits::Milliseconds => Ok(ts.truncate_milliseconds().into()),
1902-
DateTimeUnits::Microseconds => Ok(ts.truncate_microseconds().into()),
1903-
DateTimeUnits::Epoch
1904-
| DateTimeUnits::Timezone
1905-
| DateTimeUnits::TimezoneHour
1906-
| DateTimeUnits::TimezoneMinute
1907-
| DateTimeUnits::DayOfWeek
1908-
| DateTimeUnits::DayOfYear
1909-
| DateTimeUnits::IsoDayOfWeek
1910-
| DateTimeUnits::IsoDayOfYear => Err(EvalError::Unsupported {
1911-
feature: format!("'{}' timestamp units", units),
1912-
issue_no: None,
1913-
}),
1914-
}
1915-
}
1916-
19171885
fn date_trunc_interval<'a>(a: Datum, b: Datum) -> Result<Datum<'a>, EvalError> {
19181886
let mut interval = b.unwrap_interval();
19191887
let units = a.unwrap_str();
@@ -1943,40 +1911,6 @@ fn timezone_time(tz: Timezone, t: NaiveTime, wall_time: &NaiveDateTime) -> Datum
19431911
(t + offset).into()
19441912
}
19451913

1946-
/// Converts the timestamp `dt`, which is assumed to be in the time of the timezone `tz` to a timestamptz in UTC.
1947-
/// This operation is fallible because certain timestamps at timezones that observe DST are simply impossible or
1948-
/// ambiguous. In case of ambiguity (when a hour repeats) we will prefer the latest variant, and when an hour is
1949-
/// impossible, we will attempt to fix it by advancing it. For example, `EST` and `2020-11-11T12:39:14` would return
1950-
/// `2020-11-11T17:39:14Z`. A DST observing timezone like `America/New_York` would cause the following DST anomalies:
1951-
/// `2020-11-01T00:59:59` -> `2020-11-01T04:59:59Z` and `2020-11-01T01:00:00` -> `2020-11-01T06:00:00Z`
1952-
/// `2020-03-08T02:59:59` -> `2020-03-08T07:59:59Z` and `2020-03-08T03:00:00` -> `2020-03-08T07:00:00Z`
1953-
fn timezone_timestamp(tz: Timezone, mut dt: NaiveDateTime) -> Result<Datum<'static>, EvalError> {
1954-
let offset = match tz {
1955-
Timezone::FixedOffset(offset) => offset,
1956-
Timezone::Tz(tz) => match tz.offset_from_local_datetime(&dt).latest() {
1957-
Some(offset) => offset.fix(),
1958-
None => {
1959-
dt += Duration::hours(1);
1960-
tz.offset_from_local_datetime(&dt)
1961-
.latest()
1962-
.ok_or(EvalError::InvalidTimezoneConversion)?
1963-
.fix()
1964-
}
1965-
},
1966-
};
1967-
Ok(DateTime::from_utc(dt - offset, Utc).into())
1968-
}
1969-
1970-
/// Converts the UTC timestamptz `utc` to the local timestamp of the timezone `tz`.
1971-
/// For example, `EST` and `2020-11-11T17:39:14Z` would return `2020-11-11T12:39:14`.
1972-
fn timezone_timestamptz(tz: Timezone, utc: DateTime<Utc>) -> Datum<'static> {
1973-
let offset = match tz {
1974-
Timezone::FixedOffset(offset) => offset,
1975-
Timezone::Tz(tz) => tz.offset_from_utc_datetime(&utc.naive_utc()).fix(),
1976-
};
1977-
(utc.naive_utc() + offset).into()
1978-
}
1979-
19801914
/// Converts the time datum `b`, which is assumed to be in UTC, to the timezone that the interval datum `a` is assumed
19811915
/// to represent. The interval is not allowed to hold months, but there are no limits on the amount of seconds.
19821916
/// The interval acts like a `chrono::FixedOffset`, without the `-86,400 < x < 86,400` limitation.
@@ -2334,11 +2268,11 @@ impl BinaryFunc {
23342268
}
23352269
BinaryFunc::TimezoneTimestamp => {
23362270
eager!(|a: Datum, b: Datum| parse_timezone(a.unwrap_str())
2337-
.and_then(|tz| timezone_timestamp(tz, b.unwrap_timestamp())))
2271+
.and_then(|tz| Ok(timezone_timestamp(tz, b.unwrap_timestamp())?.into())))
23382272
}
23392273
BinaryFunc::TimezoneTimestampTz => {
23402274
eager!(|a: Datum, b: Datum| parse_timezone(a.unwrap_str())
2341-
.map(|tz| timezone_timestamptz(tz, b.unwrap_timestamptz())))
2275+
.map(|tz| timezone_timestamptz(tz, b.unwrap_timestamptz()).into()))
23422276
}
23432277
BinaryFunc::TimezoneTime { wall_time } => {
23442278
eager!(
@@ -3215,14 +3149,14 @@ pub enum UnaryFunc {
32153149
ExtractTimestampTz(ExtractTimestampTz),
32163150
DatePartTimestamp(DatePartTimestamp),
32173151
DatePartTimestampTz(DatePartTimestampTz),
3152+
DateTruncTimestamp(DateTruncTimestamp),
3153+
DateTruncTimestampTz(DateTruncTimestampTz),
3154+
TimezoneTimestamp(TimezoneTimestamp),
3155+
TimezoneTimestampTz(TimezoneTimestampTz),
32183156

32193157
ExtractDate(DateTimeUnits),
32203158
ExtractTime(DateTimeUnits),
32213159
DatePartTime(DateTimeUnits),
3222-
DateTruncTimestamp(DateTimeUnits),
3223-
DateTruncTimestampTz(DateTimeUnits),
3224-
TimezoneTimestamp(Timezone),
3225-
TimezoneTimestampTz(Timezone),
32263160
TimezoneTime {
32273161
tz: Timezone,
32283162
wall_time: NaiveDateTime,
@@ -3532,7 +3466,11 @@ derive_unary!(
35323466
ExtractTimestamp,
35333467
ExtractTimestampTz,
35343468
DatePartTimestamp,
3535-
DatePartTimestampTz
3469+
DatePartTimestampTz,
3470+
DateTruncTimestamp,
3471+
DateTruncTimestampTz,
3472+
TimezoneTimestamp,
3473+
TimezoneTimestampTz
35363474
);
35373475

35383476
impl UnaryFunc {
@@ -3743,6 +3681,10 @@ impl UnaryFunc {
37433681
| ExtractTimestampTz(_)
37443682
| DatePartTimestamp(_)
37453683
| DatePartTimestampTz(_)
3684+
| DateTruncTimestamp(_)
3685+
| DateTruncTimestampTz(_)
3686+
| TimezoneTimestamp(_)
3687+
| TimezoneTimestampTz(_)
37463688
| Chr(_) => unreachable!(),
37473689
CastRecordToString { ty }
37483690
| CastArrayToString { ty }
@@ -3758,10 +3700,6 @@ impl UnaryFunc {
37583700
ExtractTime(units) => date_part_time_inner::<Numeric>(*units, a),
37593701
ExtractDate(units) => extract_date_inner(*units, a),
37603702
DatePartTime(units) => date_part_time_inner::<f64>(*units, a),
3761-
DateTruncTimestamp(units) => date_trunc_inner(*units, a.unwrap_timestamp()),
3762-
DateTruncTimestampTz(units) => date_trunc_inner(*units, a.unwrap_timestamptz()),
3763-
TimezoneTimestamp(tz) => timezone_timestamp(*tz, a.unwrap_timestamp()),
3764-
TimezoneTimestampTz(tz) => Ok(timezone_timestamptz(*tz, a.unwrap_timestamptz())),
37653703
TimezoneTime { tz, wall_time } => Ok(timezone_time(*tz, a.unwrap_time(), wall_time)),
37663704
RecordGet(i) => Ok(record_get(a, *i)),
37673705
ListLength => list_length(a),
@@ -3974,6 +3912,10 @@ impl UnaryFunc {
39743912
| ExtractTimestampTz(_)
39753913
| DatePartTimestamp(_)
39763914
| DatePartTimestampTz(_)
3915+
| DateTruncTimestamp(_)
3916+
| DateTruncTimestampTz(_)
3917+
| TimezoneTimestamp(_)
3918+
| TimezoneTimestampTz(_)
39773919
| Chr(_) => unreachable!(),
39783920

39793921
CastRecordToString { .. }
@@ -3984,10 +3926,6 @@ impl UnaryFunc {
39843926

39853927
TimezoneTime { .. } => ScalarType::Time.nullable(nullable),
39863928

3987-
TimezoneTimestampTz(_) => ScalarType::Timestamp.nullable(nullable),
3988-
3989-
TimezoneTimestamp(_) => ScalarType::TimestampTz.nullable(nullable),
3990-
39913929
CastRecord1ToRecord2 { return_ty, .. } => {
39923930
return_ty.without_modifiers().nullable(nullable)
39933931
}
@@ -4000,9 +3938,6 @@ impl UnaryFunc {
40003938

40013939
DatePartTime(_) => ScalarType::Float64.nullable(nullable),
40023940

4003-
DateTruncTimestamp(_) => ScalarType::Timestamp.nullable(nullable),
4004-
DateTruncTimestampTz(_) => ScalarType::TimestampTz.nullable(nullable),
4005-
40063941
RecordGet(i) => match input_type.scalar_type {
40073942
ScalarType::Record { mut fields, .. } => {
40083943
let (_name, mut ty) = fields.swap_remove(*i);
@@ -4228,6 +4163,10 @@ impl UnaryFunc {
42284163
| ExtractTimestampTz(_)
42294164
| DatePartTimestamp(_)
42304165
| DatePartTimestampTz(_)
4166+
| DateTruncTimestamp(_)
4167+
| DateTruncTimestampTz(_)
4168+
| TimezoneTimestamp(_)
4169+
| TimezoneTimestampTz(_)
42314170
| Chr(_) => unreachable!(),
42324171
// Return null if the inner field is null
42334172
RecordGet(_) => true,
@@ -4238,13 +4177,10 @@ impl UnaryFunc {
42384177
| CastMapToString { .. }
42394178
| CastInt2VectorToString => false,
42404179
TimezoneTime { .. } => false,
4241-
TimezoneTimestampTz(_) => false,
4242-
TimezoneTimestamp(_) => false,
42434180
CastList1ToList2 { .. } | CastRecord1ToRecord2 { .. } => false,
42444181
ListLength | MapLength => false,
42454182
ExtractTime(_) | ExtractDate(_) => false,
42464183
DatePartTime(_) => false,
4247-
DateTruncTimestamp(_) | DateTruncTimestampTz(_) => false,
42484184
RescaleNumeric(_) => false,
42494185
}
42504186
}
@@ -4352,6 +4288,10 @@ impl UnaryFunc {
43524288
| ExtractTimestampTz(_)
43534289
| DatePartTimestamp(_)
43544290
| DatePartTimestampTz(_)
4291+
| DateTruncTimestamp(_)
4292+
| DateTruncTimestampTz(_)
4293+
| TimezoneTimestamp(_)
4294+
| TimezoneTimestampTz(_)
43554295
| CastVarCharToString(_) => unreachable!(),
43564296
_ => false,
43574297
}
@@ -4554,6 +4494,10 @@ impl UnaryFunc {
45544494
| ExtractTimestampTz(_)
45554495
| DatePartTimestamp(_)
45564496
| DatePartTimestampTz(_)
4497+
| DateTruncTimestamp(_)
4498+
| DateTruncTimestampTz(_)
4499+
| TimezoneTimestamp(_)
4500+
| TimezoneTimestampTz(_)
45574501
| Chr(_) => unreachable!(),
45584502
CastRecordToString { .. } => f.write_str("recordtostr"),
45594503
CastRecord1ToRecord2 { .. } => f.write_str("record1torecord2"),
@@ -4565,10 +4509,6 @@ impl UnaryFunc {
45654509
ExtractTime(units) => write!(f, "extract_{}_t", units),
45664510
ExtractDate(units) => write!(f, "extract_{}_d", units),
45674511
DatePartTime(units) => write!(f, "date_part_{}_t", units),
4568-
DateTruncTimestamp(units) => write!(f, "date_trunc_{}_ts", units),
4569-
DateTruncTimestampTz(units) => write!(f, "date_trunc_{}_tstz", units),
4570-
TimezoneTimestamp(tz) => write!(f, "timezone_{}_ts", tz),
4571-
TimezoneTimestampTz(tz) => write!(f, "timezone_{}_tstz", tz),
45724512
TimezoneTime { tz, .. } => write!(f, "timezone_{}_t", tz),
45734513
RecordGet(i) => write!(f, "record_get[{}]", i),
45744514
ListLength => f.write_str("list_length"),

0 commit comments

Comments
 (0)