From a33650a69e28585dad4dfb5897e38e6c16de8811 Mon Sep 17 00:00:00 2001 From: pyz4 <42039243+pyz4@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:20:54 -0400 Subject: [PATCH] fix(polars): cast as date now returns Date type instead of Datetime (#15574) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR fixes the bug where various commands that cast a column as a `date` type would return `datetime` rather than the intended type `date`. Affected commands include `polars into-df --schema`, `polars into-lazy --schema`, `polars as-date`, and `polars cast date`. This bug derives from the fact that Nushell uses the `date` type to denote a datetime type whereas polars differentiates between `Date` and `Datetime` types. By default, this PR retains the behavior that a Nushell `date` type will be mapped to a polars `Datetime` unless otherwise specified. ```nushell # Current (erroneous) implementation > [[a]; [2025-03-20]] | polars into-df --schema {a: "date"} | polars schema ╭───┬──────────────╮ │ a │ datetime │ ╰───┴──────────────╯ # Fixed implementation > [[a]; [2025-03-20]] | polars into-df --schema {a: "date"} | polars schema ╭───┬──────╮ │ a │ date │ ╰───┴──────╯ # Fixed implementation: by default, Nushell dates map to datetime > [[a]; [2025-03-20]] | polars into-df | polars schema ╭───┬───────────────────╮ │ a │ datetime │ ╰───┴───────────────────╯ ``` # User-Facing Changes Soft breaking change: users previously who wanted to cast a date column to type `date` can now expect the output to be type `date` instead of `datetime`. # Tests + Formatting Example test added to `polars as-date` command. # After Submitting --- .../src/dataframe/command/datetime/as_date.rs | 13 ++++++++++++- .../values/nu_dataframe/conversion.rs | 18 ++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/crates/nu_plugin_polars/src/dataframe/command/datetime/as_date.rs b/crates/nu_plugin_polars/src/dataframe/command/datetime/as_date.rs index 41dadd8646..aa36e44ece 100644 --- a/crates/nu_plugin_polars/src/dataframe/command/datetime/as_date.rs +++ b/crates/nu_plugin_polars/src/dataframe/command/datetime/as_date.rs @@ -4,7 +4,8 @@ use super::super::super::values::NuDataFrame; use nu_plugin::{EngineInterface, EvaluatedCall, PluginCommand}; use nu_protocol::{ - Category, Example, LabeledError, PipelineData, ShellError, Signature, SyntaxShape, Type, + record, Category, Example, LabeledError, PipelineData, ShellError, Signature, Span, + SyntaxShape, Type, Value, }; use polars::prelude::{IntoSeries, StringMethods}; @@ -52,6 +53,16 @@ impl PluginCommand for AsDate { example: r#"["2021-12-30" "2021-12-31 21:00:00"] | polars into-df | polars as-date "%Y-%m-%d" --not-exact"#, result: None, }, + Example { + description: "Output is of date type", + example: r#"["2021-12-30" "2021-12-31 21:00:00"] | polars into-df | polars as-date "%Y-%m-%d" --not-exact | polars schema"#, + result: Some(Value::record( + record! { + "date" => Value::string("date", Span::test_data()), + }, + Span::test_data(), + )), + }, ] } diff --git a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs index b84e85a632..8b061b3945 100644 --- a/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs +++ b/crates/nu_plugin_polars/src/dataframe/values/nu_dataframe/conversion.rs @@ -12,8 +12,8 @@ use polars::datatypes::{AnyValue, PlSmallStr}; use polars::prelude::{ ChunkAnyValue, Column as PolarsColumn, DataFrame, DataType, DatetimeChunked, Float32Type, Float64Type, Int16Type, Int32Type, Int64Type, Int8Type, IntoSeries, ListBooleanChunkedBuilder, - ListBuilderTrait, ListPrimitiveChunkedBuilder, ListStringChunkedBuilder, ListType, NamedFrom, - NewChunkedArray, ObjectType, PolarsError, Schema, SchemaExt, Series, StructChunked, + ListBuilderTrait, ListPrimitiveChunkedBuilder, ListStringChunkedBuilder, ListType, LogicalType, + NamedFrom, NewChunkedArray, ObjectType, PolarsError, Schema, SchemaExt, Series, StructChunked, TemporalMethods, TimeUnit, UInt16Type, UInt32Type, UInt64Type, UInt8Type, }; @@ -441,10 +441,16 @@ fn typed_column_to_series(name: PlSmallStr, column: TypedColumn) -> Result::from_iter_options(name, it) - .into_datetime(TimeUnit::Nanoseconds, None); - - Ok(res.into_series()) + ChunkedArray::::from_iter_options(name, it) + .into_datetime(TimeUnit::Nanoseconds, None) + .cast_with_options(&DataType::Date, Default::default()) + .map_err(|e| ShellError::GenericError { + error: "Error parsing date".into(), + msg: "".into(), + span: None, + help: Some(e.to_string()), + inner: vec![], + }) } DataType::Datetime(tu, maybe_tz) => { let dates = column