risingwave_expr_impl/scalar/
to_timestamp.rs1use chrono::format::Parsed;
16use risingwave_common::types::{Date, Timestamp, Timestamptz};
17use risingwave_expr::{ExprError, Result, function};
18
19use super::timestamptz::{timestamp_at_time_zone, timestamptz_at_time_zone};
20use super::to_char::ChronoPattern;
21
22#[inline(always)]
24fn parse(s: &str, tmpl: &ChronoPattern) -> Result<Parsed> {
25 let mut parsed = Parsed::new();
26 chrono::format::parse(&mut parsed, s, tmpl.borrow_dependent().iter())?;
27
28 if parsed.year.is_none()
33 && parsed.year_div_100.is_none()
34 && parsed.year_mod_100.is_none()
35 && parsed.isoyear.is_none()
36 && parsed.isoyear_div_100.is_none()
37 && parsed.isoyear_mod_100.is_none()
38 {
39 parsed.set_year(-1).unwrap();
40 }
41
42 if parsed.month.is_none()
44 && parsed.week_from_mon.is_none()
45 && parsed.week_from_sun.is_none()
46 && parsed.isoweek.is_none()
47 {
48 parsed.set_month(1).unwrap();
49 }
50
51 if parsed.day.is_none() && parsed.ordinal.is_none() {
53 parsed.set_day(1).unwrap();
54 }
55
56 parsed.hour_div_12.get_or_insert(0);
58
59 parsed.hour_mod_12.get_or_insert(0);
61 parsed.minute.get_or_insert(0);
62
63 Ok(parsed)
66}
67
68#[function(
69 "char_to_timestamptz(varchar, varchar) -> timestamp",
70 prebuild = "ChronoPattern::compile($1)",
71 deprecated
72)]
73pub fn to_timestamp_legacy(s: &str, tmpl: &ChronoPattern) -> Result<Timestamp> {
74 let parsed = parse(s, tmpl)?;
75 match parsed.offset {
76 None => Ok(parsed.to_naive_datetime_with_offset(0)?.into()),
77 Some(_) => timestamptz_at_time_zone(parsed.to_datetime()?.into(), "UTC"),
80 }
81}
82
83#[function(
84 "char_to_timestamptz(varchar, varchar, varchar) -> timestamptz",
85 prebuild = "ChronoPattern::compile($1)"
86)]
87pub fn to_timestamp(s: &str, timezone: &str, tmpl: &ChronoPattern) -> Result<Timestamptz> {
88 let parsed = parse(s, tmpl)?;
89 Ok(match parsed.offset {
90 Some(_) => parsed.to_datetime()?.into(),
91 None => timestamp_at_time_zone(parsed.to_naive_datetime_with_offset(0)?.into(), timezone)?,
93 })
94}
95
96#[function("char_to_timestamptz(varchar, varchar) -> timestamptz", rewritten)]
97fn _to_timestamp1() {}
98
99#[function(
100 "char_to_date(varchar, varchar) -> date",
101 prebuild = "ChronoPattern::compile($1)"
102)]
103pub fn to_date(s: &str, tmpl: &ChronoPattern) -> Result<Date> {
104 let mut parsed = parse(s, tmpl)?;
105 if let Some(year) = &mut parsed.year
106 && *year < 0
107 {
108 *year += 1;
109 }
110 Ok(parsed.to_naive_date()?.into())
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_to_timestamp_legacy() {
119 for (input, format, expected) in [
122 (
123 "2020-02-03 12:34:56",
124 "yyyy-mm-dd hh24:mi:ss",
125 "2020-02-03 12:34:56",
126 ),
127 (
128 "2020-02-03 12:34:56+03:00",
129 "yyyy-mm-dd hh24:mi:ss tzh:tzm",
130 "2020-02-03 09:34:56",
131 ),
132 ] {
133 let actual = to_timestamp_legacy(input, &ChronoPattern::compile(format)).unwrap();
134 assert_eq!(actual.to_string(), expected);
135 }
136 }
137}