vegafusion_runtime/expression/compiler/builtin_functions/date_time/
date_parts.rs1use crate::expression::compiler::call::TzTransformFn;
2use crate::expression::compiler::utils::ExprHelpers;
3use crate::task_graph::timezone::RuntimeTzConfig;
4use crate::transform::timeunit::to_timestamp_col;
5use datafusion_expr::{lit, Expr};
6use datafusion_functions::expr_fn::{date_part, floor};
7use std::sync::Arc;
8use vegafusion_common::arrow::datatypes::{DataType, TimeUnit};
9use vegafusion_common::datafusion_common::DFSchema;
10use vegafusion_core::error::Result;
11
12pub fn make_local_datepart_transform(part: &str, tx: Option<fn(Expr) -> Expr>) -> TzTransformFn {
13 let part = part.to_string();
14 let local_datepart_transform =
15 move |tz_config: &RuntimeTzConfig, args: &[Expr], schema: &DFSchema| -> Result<Expr> {
16 let arg = args.first().unwrap().clone();
17 let arg = to_timestamp_col(arg, schema, &tz_config.default_input_tz.to_string())?;
18 let mut expr = date_part(
19 lit(part.clone()),
20 arg.try_cast_to(
21 &DataType::Timestamp(
22 TimeUnit::Millisecond,
23 Some(tz_config.local_tz.to_string().into()),
24 ),
25 schema,
26 )?,
27 );
28
29 if let Some(tx) = tx {
30 expr = tx(expr)
31 }
32
33 Ok(expr)
34 };
35 Arc::new(local_datepart_transform)
36}
37
38pub fn make_utc_datepart_transform(part: &str, tx: Option<fn(Expr) -> Expr>) -> TzTransformFn {
39 let part = part.to_string();
40 let utc_datepart_transform =
41 move |tz_config: &RuntimeTzConfig, args: &[Expr], schema: &DFSchema| -> Result<Expr> {
42 let arg = to_timestamp_col(
43 args.first().unwrap().clone(),
44 schema,
45 &tz_config.default_input_tz.to_string(),
46 )?;
47 let mut expr = date_part(
48 lit(part.clone()),
49 arg.try_cast_to(
50 &DataType::Timestamp(TimeUnit::Millisecond, Some("UTC".into())),
51 schema,
52 )?,
53 );
54
55 if let Some(tx) = tx {
56 expr = tx(expr)
57 }
58
59 Ok(expr)
60 };
61 Arc::new(utc_datepart_transform)
62}
63
64lazy_static! {
65 pub static ref YEAR_TRANSFORM: TzTransformFn =
67 make_local_datepart_transform("year", None);
68 pub static ref QUARTER_TRANSFORM: TzTransformFn =
69 make_local_datepart_transform("quarter", None);
70
71 pub static ref MONTH_TRANSFORM: TzTransformFn =
73 make_local_datepart_transform(
74 "month", Some(|expr| expr - lit(1.0))
75 );
76
77 pub static ref DAYOFYEAR_TRANSFORM: TzTransformFn =
78 make_local_datepart_transform("doy", None);
79 pub static ref DATE_TRANSFORM: TzTransformFn =
80 make_local_datepart_transform("day", None);
81 pub static ref DAY_TRANSFORM: TzTransformFn =
82 make_local_datepart_transform("dow", None);
83 pub static ref HOUR_TRANSFORM: TzTransformFn =
84 make_local_datepart_transform("hour", None);
85 pub static ref MINUTE_TRANSFORM: TzTransformFn =
86 make_local_datepart_transform("minute", None);
87 pub static ref SECOND_TRANSFORM: TzTransformFn =
88 make_local_datepart_transform(
89 "second", Some(floor)
90 );
91 pub static ref MILLISECOND_TRANSFORM: TzTransformFn =
92 make_local_datepart_transform(
93 "millisecond", Some(|expr| expr % lit(1000.0))
94 );
95
96 pub static ref UTCYEAR_TRANSFORM: TzTransformFn =
98 make_utc_datepart_transform("year", None);
99 pub static ref UTCQUARTER_TRANSFORM: TzTransformFn =
100 make_utc_datepart_transform("quarter", None);
101
102 pub static ref UTCMONTH_TRANSFORM: TzTransformFn =
104 make_utc_datepart_transform(
105 "month", Some(|expr| expr - lit(1.0))
106 );
107
108 pub static ref UTCDAYOFYEAR_TRANSFORM: TzTransformFn =
109 make_utc_datepart_transform("doy", None);
110 pub static ref UTCDATE_TRANSFORM: TzTransformFn =
111 make_utc_datepart_transform("day", None);
112 pub static ref UTCDAY_TRANSFORM: TzTransformFn =
113 make_utc_datepart_transform("dow", None);
114 pub static ref UTCHOUR_TRANSFORM: TzTransformFn =
115 make_utc_datepart_transform("hour", None);
116 pub static ref UTCMINUTE_TRANSFORM: TzTransformFn =
117 make_utc_datepart_transform("minute", None);
118 pub static ref UTCSECOND_TRANSFORM: TzTransformFn =
119 make_utc_datepart_transform(
120 "second", Some(floor)
121 );
122 pub static ref UTCMILLISECOND_TRANSFORM: TzTransformFn =
123 make_utc_datepart_transform(
124 "millisecond", Some(|expr| expr % lit(1000.0))
125 );
126}