diff --git a/core/expression/src/intellisense/types/provider.rs b/core/expression/src/intellisense/types/provider.rs index d9861aeb..102625f2 100644 --- a/core/expression/src/intellisense/types/provider.rs +++ b/core/expression/src/intellisense/types/provider.rs @@ -237,6 +237,7 @@ impl TypesProvider { | ComparisonOperator::GreaterThan | ComparisonOperator::LessThanOrEqual | ComparisonOperator::GreaterThanOrEqual => match (left_type.deref(), right_type.deref()) { + (VariableType::Date | VariableType::Any, VariableType::Date | VariableType::Any) => V(VariableType::Bool), (VariableType::Number | VariableType::Any, VariableType::Number | VariableType::Any) => V(VariableType::Bool), _ => Error(format!( "Operator `{operator}` cannot be applied to types `{left_type}` and `{right_type}`." @@ -257,7 +258,7 @@ impl TypesProvider { V(VariableType::Bool) }, - (VariableType::Number, VariableType::Interval) => V(VariableType::Bool), + (VariableType::Number | VariableType::Date, VariableType::Interval) => V(VariableType::Bool), (VariableType::String, VariableType::Object(_)) => V(VariableType::Bool), (VariableType::Any, _) => V(VariableType::Bool), (_, VariableType::Any) => V(VariableType::Bool), @@ -328,7 +329,9 @@ impl TypesProvider { } Node::Interval { left, right, .. } => { let left_type = self.determine(left, scope.clone()); - if !left_type.satisfies(&VariableType::Number) { + if !left_type.satisfies(&VariableType::Number) + && !left_type.satisfies(&VariableType::Date) + { self.set_error( left, format!("Interval cannot be created from type `{left_type}`."), @@ -336,7 +339,9 @@ impl TypesProvider { } let right_type = self.determine(right, scope.clone()); - if !right_type.satisfies(&VariableType::Number) { + if !right_type.satisfies(&VariableType::Number) + && !right_type.satisfies(&VariableType::Date) + { self.set_error( right, format!("Interval cannot be created from type `{right_type}`."), @@ -352,7 +357,7 @@ impl TypesProvider { .collect(); if let FunctionKind::Closure(_) = kind { - let ptr_type = type_list[0].array_item().unwrap_or_default(); + let ptr_type = type_list[0].iterator().unwrap_or_default(); let new_type = self.determine( arguments[1], IntelliSenseScope { diff --git a/core/expression/src/variable/types/util.rs b/core/expression/src/variable/types/util.rs index 2c410c26..d48356d5 100644 --- a/core/expression/src/variable/types/util.rs +++ b/core/expression/src/variable/types/util.rs @@ -4,9 +4,10 @@ use std::collections::HashMap; use std::rc::Rc; impl VariableType { - pub fn array_item(&self) -> Option> { + pub fn iterator(&self) -> Option> { match self { VariableType::Array(item) => Some(item.clone()), + VariableType::Interval => Some(Rc::new(VariableType::Number)), _ => None, } } @@ -35,6 +36,8 @@ impl VariableType { (VariableType::String, VariableType::String) => true, (VariableType::Number, VariableType::Number) => true, (VariableType::Date, VariableType::Date) => true, + (VariableType::Number, VariableType::Date) => true, + (_, VariableType::Date) if self.widen().is_string() => true, (VariableType::Interval, VariableType::Interval) => true, (VariableType::Array(a1), VariableType::Array(a2)) => a1.satisfies(a2), (VariableType::Object(o1), VariableType::Object(o2)) => o1 @@ -71,6 +74,13 @@ impl VariableType { } } + pub fn is_string(&self) -> bool { + match self { + VariableType::String => true, + _ => false, + } + } + pub fn is_object(&self) -> bool { match self { VariableType::Any | VariableType::Object(_) => true, diff --git a/core/expression/src/vm/date/mod.rs b/core/expression/src/vm/date/mod.rs index a77dccb5..e09125ec 100644 --- a/core/expression/src/vm/date/mod.rs +++ b/core/expression/src/vm/date/mod.rs @@ -205,7 +205,6 @@ mod helper { let tz = tz_opt.unwrap_or_else(|| tz()); match var { - Variable::Null => Some(now()), Variable::Number(n) => { let n_i64 = n.to_i64()?; let date_time = match tz.timestamp_millis_opt(n_i64) { diff --git a/core/expression/tests/data/date.csv b/core/expression/tests/data/date.csv index 99d07bfa..dc879fd8 100644 --- a/core/expression/tests/data/date.csv +++ b/core/expression/tests/data/date.csv @@ -111,6 +111,7 @@ d('2023-10-15T14:30:45Z').format('Day %j of year %Y');;'Day 288 of year 2023' d('2023-10-15T14:30:45.123Z').format('%H:%M:%S.%f');;'14:30:45.123000000' # Date validations +d(null).isValid();;false d('foo').isValid();;false d('2023-13-01').isValid();;false d('2023-02-30').isValid();;false