diff --git a/crates/nu-command/src/formats/from/toml.rs b/crates/nu-command/src/formats/from/toml.rs index ee3bdff722..5af85cdeb2 100644 --- a/crates/nu-command/src/formats/from/toml.rs +++ b/crates/nu-command/src/formats/from/toml.rs @@ -4,6 +4,7 @@ use nu_protocol::{ record, Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Span, Type, Value, }; +use std::str::FromStr; #[derive(Clone)] pub struct FromToml; @@ -23,6 +24,19 @@ impl Command for FromToml { "Parse text as .toml and create record." } + fn run( + &self, + _engine_state: &EngineState, + _stack: &mut Stack, + call: &Call, + input: PipelineData, + ) -> Result { + let span = call.head; + let (mut string_input, span, metadata) = input.collect_string_strict(span)?; + string_input.push('\n'); + Ok(convert_string_to_value(string_input, span)?.into_pipeline_data_with_metadata(metadata)) + } + fn examples(&self) -> Vec { vec![ Example { @@ -45,19 +59,6 @@ b = [1, 2]' | from toml", }, ] } - - fn run( - &self, - __engine_state: &EngineState, - _stack: &mut Stack, - call: &Call, - input: PipelineData, - ) -> Result { - let span = call.head; - let (mut string_input, span, metadata) = input.collect_string_strict(span)?; - string_input.push('\n'); - Ok(convert_string_to_value(string_input, span)?.into_pipeline_data_with_metadata(metadata)) - } } fn convert_toml_to_value(value: &toml::Value, span: Span) -> Value { @@ -80,7 +81,13 @@ fn convert_toml_to_value(value: &toml::Value, span: Span) -> Value { span, ), toml::Value::String(s) => Value::string(s.clone(), span), - toml::Value::Datetime(d) => Value::string(d.to_string(), span), + toml::Value::Datetime(d) => match chrono::DateTime::from_str(&d.to_string()) { + Ok(nushell_date) => Value::date(nushell_date, span), + // in the unlikely event that parsing goes wrong, this function still returns a valid + // nushell date (however the default one). This decision was made to make the output of + // this function uniform amongst all eventualities + Err(_) => Value::date(chrono::DateTime::default(), span), + }, } } @@ -101,6 +108,8 @@ pub fn convert_string_to_value(string_input: String, span: Span) -> Result Result toml::Value::Integer(*val), Value::Filesize { val, .. } => toml::Value::Integer(*val), Value::Duration { val, .. } => toml::Value::String(val.to_string()), - Value::Date { val, .. } => toml::Value::String(val.to_string()), + Value::Date { val, .. } => { + toml::Value::String(val.to_rfc3339_opts(SecondsFormat::AutoSi, false)) + } Value::Range { .. } => toml::Value::String("".to_string()), Value::Float { val, .. } => toml::Value::Float(*val), Value::String { val, .. } | Value::QuotedString { val, .. } => { @@ -171,6 +174,7 @@ fn to_toml( #[cfg(test)] mod tests { use super::*; + use chrono::TimeZone; #[test] fn test_examples() { @@ -179,6 +183,25 @@ mod tests { test_examples(ToToml {}) } + #[test] + fn to_toml_creates_correct_date() { + let engine_state = EngineState::new(); + + let test_date = Value::date( + chrono::FixedOffset::east_opt(60 * 120) + .unwrap() + .with_ymd_and_hms(1980, 10, 12, 10, 12, 44) + .unwrap(), + Span::test_data(), + ); + + let reference_date = toml::Value::String(String::from("1980-10-12T10:12:44+02:00")); + + let result = helper(&engine_state, &test_date); + + assert!(result.is_ok_and(|res| res == reference_date)); + } + #[test] fn test_value_to_toml_value() { //