diff --git a/crates/nu_plugin_polars/src/dataframe/command/data/filter.rs b/crates/nu_plugin_polars/src/dataframe/command/data/filter.rs index 0c4e9372e2..34d0fa6873 100644 --- a/crates/nu_plugin_polars/src/dataframe/command/data/filter.rs +++ b/crates/nu_plugin_polars/src/dataframe/command/data/filter.rs @@ -39,20 +39,60 @@ impl PluginCommand for LazyFilter { } fn examples(&self) -> Vec { - vec![Example { - description: "Filter dataframe using an expression", - example: - "[[a b]; [6 2] [4 2] [2 2]] | polars into-df | polars filter ((polars col a) >= 4)", - result: Some( + vec![ + Example { + description: "Filter dataframe using an expression", + example: + "[[a b]; [6 2] [4 2] [2 2]] | polars into-df | polars filter ((polars col a) >= 4)", + result: Some( + NuDataFrame::try_from_columns( + vec![ + Column::new( + "a".to_string(), + vec![Value::test_int(6), Value::test_int(4)], + ), + Column::new( + "b".to_string(), + vec![Value::test_int(2), Value::test_int(2)], + ), + ], + None, + ) + .expect("simple df for test should not fail") + .into_value(Span::test_data()), + ), + }, + Example { + description: "Filter dataframe for rows where dt is within the last 2 days of the maximum dt value", + example: + "[[dt val]; [2025-04-01 1] [2025-04-02 2] [2025-04-03 3] [2025-04-04 4]] | polars into-df | polars filter ((polars col dt) > ((polars col dt | polars max | $in - 2day)))", + result: Some( NuDataFrame::try_from_columns( vec![ Column::new( - "a".to_string(), - vec![Value::test_int(6), Value::test_int(4)], + "dt".to_string(), + vec![ + Value::date( + chrono::DateTime::parse_from_str( + "2025-04-03 00:00:00 +0000", + "%Y-%m-%d %H:%M:%S %z", + ) + .expect("date calculation should not fail in test"), + Span::test_data(), + ), + Value::date( + chrono::DateTime::parse_from_str( + "2025-04-04 00:00:00 +0000", + "%Y-%m-%d %H:%M:%S %z", + ) + .expect("date calculation should not fail in test"), + Span::test_data(), + ), + ] ), Column::new( - "b".to_string(), - vec![Value::test_int(2), Value::test_int(2)], + "val".to_string(), + vec![Value::test_int(3), Value::test_int(4)], ), ], None, @@ -60,7 +100,8 @@ impl PluginCommand for LazyFilter { .expect("simple df for test should not fail") .into_value(Span::test_data()), ), - }] + }, + ] } fn run( diff --git a/crates/nu_plugin_polars/src/dataframe/command/data/lit.rs b/crates/nu_plugin_polars/src/dataframe/command/data/lit.rs index 241058fb5c..783117ecbd 100644 --- a/crates/nu_plugin_polars/src/dataframe/command/data/lit.rs +++ b/crates/nu_plugin_polars/src/dataframe/command/data/lit.rs @@ -30,14 +30,40 @@ impl PluginCommand for ExprLit { } fn examples(&self) -> Vec { - vec![Example { - description: "Created a literal expression and converts it to a nu object", - example: "polars lit 2 | polars into-nu", - result: Some(Value::test_record(record! { - "expr" => Value::test_string("literal"), - "value" => Value::test_string("dyn int: 2"), - })), - }] + vec![ + Example { + description: "Created a literal expression and converts it to a nu object", + example: "polars lit 2 | polars into-nu", + result: Some(Value::test_record(record! { + "expr" => Value::test_string("literal"), + "value" => Value::test_string("dyn int: 2"), + })), + }, + Example { + description: "Create a literal expression from date", + example: "polars lit 2025-04-13 | polars into-nu", + result: Some(Value::test_record(record! { + "expr" => Value::test_record(record! { + "expr" => Value::test_string("literal"), + "value" => Value::test_string("dyn int: 1744502400000000000"), + }), + "dtype" => Value::test_string("Datetime(Nanoseconds, None)"), + "cast_options" => Value::test_string("STRICT") + })), + }, + Example { + description: "Create a literal expression from duration", + example: "polars lit 3hr | polars into-nu", + result: Some(Value::test_record(record! { + "expr" => Value::test_record(record! { + "expr" => Value::test_string("literal"), + "value" => Value::test_string("dyn int: 10800000000000"), + }), + "dtype" => Value::test_string("Duration(Nanoseconds)"), + "cast_options" => Value::test_string("STRICT") + })), + }, + ] } fn search_terms(&self) -> Vec<&str> { diff --git a/crates/nu_plugin_polars/src/dataframe/values/nu_expression/mod.rs b/crates/nu_plugin_polars/src/dataframe/values/nu_expression/mod.rs index 7b60f9b1e4..54acb63a9d 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/nu_expression/mod.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/nu_expression/mod.rs @@ -523,6 +523,32 @@ impl CustomValueSupport for NuExpression { Value::Int { val, .. } => Ok(val.to_owned().lit().into()), Value::Bool { val, .. } => Ok(val.to_owned().lit().into()), Value::Float { val, .. } => Ok(val.to_owned().lit().into()), + Value::Date { val, .. } => val + .to_owned() + .timestamp_nanos_opt() + .ok_or_else(|| ShellError::GenericError { + error: "Integer overflow".into(), + msg: "Provided datetime in nanoseconds is too large for i64".into(), + span: Some(value.span()), + help: None, + inner: vec![], + }) + .map(|nanos| -> NuExpression { + nanos + .lit() + .strict_cast(polars::prelude::DataType::Datetime( + polars::prelude::TimeUnit::Nanoseconds, + None, + )) + .into() + }), + Value::Duration { val, .. } => Ok(val + .to_owned() + .lit() + .strict_cast(polars::prelude::DataType::Duration( + polars::prelude::TimeUnit::Nanoseconds, + )) + .into()), x => Err(ShellError::CantConvert { to_type: "lazy expression".into(), from_type: x.get_type().to_string(),