mz_expr/scalar/func/impls/
mz_timestamp.rs
1use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc};
11use mz_ore::result::ResultExt;
12use mz_repr::adt::date::Date;
13use mz_repr::adt::numeric::Numeric;
14use mz_repr::adt::timestamp::CheckedTimestamp;
15use mz_repr::{Timestamp, strconv};
16
17use crate::EvalError;
18
19sqlfunc!(
25 #[sqlname = "mz_timestamp_to_text"]
26 #[preserves_uniqueness = true]
27 #[inverse = to_unary!(super::CastStringToMzTimestamp)]
28 fn cast_mz_timestamp_to_string(a: Timestamp) -> String {
29 let mut buf = String::new();
30 strconv::format_mz_timestamp(&mut buf, a);
31 buf
32 }
33);
34
35sqlfunc!(
36 #[sqlname = "text_to_mz_timestamp"]
37 #[preserves_uniqueness = false]
38 #[inverse = to_unary!(super::CastMzTimestampToString)]
39 fn cast_string_to_mz_timestamp(a: String) -> Result<Timestamp, EvalError> {
40 strconv::parse_mz_timestamp(&a).err_into()
41 }
42);
43
44sqlfunc!(
45 #[sqlname = "numeric_to_mz_timestamp"]
46 #[preserves_uniqueness = true]
47 #[is_monotone = true]
48 fn cast_numeric_to_mz_timestamp(a: Numeric) -> Result<Timestamp, EvalError> {
49 a.try_into()
51 .map_err(|_| EvalError::MzTimestampOutOfRange(a.to_string().into()))
52 }
53);
54
55sqlfunc!(
56 #[sqlname = "uint8_to_mz_timestamp"]
57 #[preserves_uniqueness = true]
58 #[is_monotone = true]
59 fn cast_uint64_to_mz_timestamp(a: u64) -> Timestamp {
60 a.into()
61 }
62);
63
64sqlfunc!(
65 #[sqlname = "uint4_to_mz_timestamp"]
66 #[preserves_uniqueness = true]
67 #[is_monotone = true]
68 fn cast_uint32_to_mz_timestamp(a: u32) -> Timestamp {
69 u64::from(a).into()
70 }
71);
72
73sqlfunc!(
74 #[sqlname = "bigint_to_mz_timestamp"]
75 #[preserves_uniqueness = true]
76 #[is_monotone = true]
77 fn cast_int64_to_mz_timestamp(a: i64) -> Result<Timestamp, EvalError> {
78 a.try_into()
79 .map_err(|_| EvalError::MzTimestampOutOfRange(a.to_string().into()))
80 }
81);
82
83sqlfunc!(
84 #[sqlname = "integer_to_mz_timestamp"]
85 #[preserves_uniqueness = true]
86 #[is_monotone = true]
87 fn cast_int32_to_mz_timestamp(a: i32) -> Result<Timestamp, EvalError> {
88 i64::from(a)
89 .try_into()
90 .map_err(|_| EvalError::MzTimestampOutOfRange(a.to_string().into()))
91 }
92);
93
94sqlfunc!(
95 #[sqlname = "timestamp_tz_to_mz_timestamp"]
96 #[is_monotone = true]
97 fn cast_timestamp_tz_to_mz_timestamp(
98 a: CheckedTimestamp<DateTime<Utc>>,
99 ) -> Result<Timestamp, EvalError> {
100 a.timestamp_millis()
101 .try_into()
102 .map_err(|_| EvalError::MzTimestampOutOfRange(a.to_string().into()))
103 }
104);
105
106sqlfunc!(
107 #[sqlname = "timestamp_to_mz_timestamp"]
108 #[is_monotone = true]
109 fn cast_timestamp_to_mz_timestamp(
110 a: CheckedTimestamp<NaiveDateTime>,
111 ) -> Result<Timestamp, EvalError> {
112 a.and_utc()
113 .timestamp_millis()
114 .try_into()
115 .map_err(|_| EvalError::MzTimestampOutOfRange(a.to_string().into()))
116 }
117);
118
119sqlfunc!(
120 #[sqlname = "date_to_mz_timestamp"]
121 #[preserves_uniqueness = true]
122 #[is_monotone = true]
123 fn cast_date_to_mz_timestamp(a: Date) -> Result<Timestamp, EvalError> {
124 let ts = CheckedTimestamp::try_from(NaiveDate::from(a).and_hms_opt(0, 0, 0).unwrap())?;
125 ts.and_utc()
126 .timestamp_millis()
127 .try_into()
128 .map_err(|_| EvalError::MzTimestampOutOfRange(a.to_string().into()))
129 }
130);
131
132sqlfunc!(
133 #[sqlname = "mz_timestamp_to_timestamp"]
134 #[preserves_uniqueness = true]
135 #[inverse = to_unary!(super::CastTimestampToMzTimestamp)]
136 fn cast_mz_timestamp_to_timestamp(
137 a: Timestamp,
138 ) -> Result<CheckedTimestamp<NaiveDateTime>, EvalError> {
139 let ms: i64 = a.try_into().map_err(|_| EvalError::TimestampOutOfRange)?;
140 let ct = DateTime::from_timestamp_millis(ms).and_then(|dt| {
141 let ct: Option<CheckedTimestamp<NaiveDateTime>> = dt.naive_utc().try_into().ok();
142 ct
143 });
144 ct.ok_or(EvalError::TimestampOutOfRange)
145 }
146);
147
148sqlfunc!(
149 #[sqlname = "mz_timestamp_to_timestamp_tz"]
150 #[preserves_uniqueness = true]
151 #[inverse = to_unary!(super::CastTimestampTzToMzTimestamp)]
152 fn cast_mz_timestamp_to_timestamp_tz(
153 a: Timestamp,
154 ) -> Result<CheckedTimestamp<DateTime<Utc>>, EvalError> {
155 let ms: i64 = a.try_into().map_err(|_| EvalError::TimestampOutOfRange)?;
156 let ct = DateTime::from_timestamp_millis(ms).and_then(|dt| {
157 let ct: Option<CheckedTimestamp<DateTime<Utc>>> = dt.try_into().ok();
158 ct
159 });
160 ct.ok_or(EvalError::TimestampOutOfRange)
161 }
162);
163
164sqlfunc!(
165 #[sqlname = "step_mz_timestamp"]
166 #[preserves_uniqueness = true]
167 #[is_monotone = true]
168 fn step_mz_timestamp(a: Timestamp) -> Result<Timestamp, EvalError> {
169 a.checked_add(1).ok_or(EvalError::MzTimestampStepOverflow)
170 }
171);