From d52ec65f18232cf70c380e1f340f727bc39100e8 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Wed, 6 Nov 2024 07:14:00 -0600 Subject: [PATCH] update human-date-parser conversion to use local timezone (#14266) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description This PR tries to fix https://github.com/nushell/nushell/issues/14195 by setting the local time and timezone after conversion without changing the time. ### Before ```nushell ❯ 'in 10 minutes' | into datetime Tue, 5 Nov 2024 12:59:58 -0600 (in 9 minutes) ❯ 'yesterday' | into datetime Sun, 3 Nov 2024 18:00:00 -0600 (2 days ago) ❯ 'tomorrow' | into datetime Tue, 5 Nov 2024 18:00:00 -0600 (in 5 hours) ❯ 'today' | into datetime Mon, 4 Nov 2024 18:00:00 -0600 (18 hours ago) ``` ### After (these are correct) ```nushell ❯ 'in 10 minutes' | into datetime Tue, 5 Nov 2024 12:58:44 -0600 (in 9 minutes) ❯ 'yesterday' | into datetime Mon, 4 Nov 2024 12:49:04 -0600 (a day ago) ❯ 'tomorrow' | into datetime Wed, 6 Nov 2024 12:49:20 -0600 (in a day) ❯ 'today' | into datetime Tue, 5 Nov 2024 12:52:06 -0600 (now) ``` # User-Facing Changes # Tests + Formatting # After Submitting --- .../src/conversions/into/datetime.rs | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/crates/nu-command/src/conversions/into/datetime.rs b/crates/nu-command/src/conversions/into/datetime.rs index 68fcc31420..fd183b43bd 100644 --- a/crates/nu-command/src/conversions/into/datetime.rs +++ b/crates/nu-command/src/conversions/into/datetime.rs @@ -1,5 +1,5 @@ use crate::{generate_strftime_list, parse_date_from_string}; -use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, NaiveTime, TimeZone, Utc}; +use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, TimeZone, Utc}; use human_date_parser::{from_human_time, ParseResult}; use nu_cmd_base::input_handler::{operate, CmdArgument}; use nu_engine::command_prelude::*; @@ -275,12 +275,13 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value { if let Ok(date) = from_human_time(&input_val) { match date { ParseResult::Date(date) => { - let time = NaiveTime::from_hms_opt(0, 0, 0).expect("valid time"); + let time = Local::now().time(); let combined = date.and_time(time); - let dt_fixed = DateTime::from_naive_utc_and_offset( - combined, - *Local::now().offset(), - ); + let local_offset = *Local::now().offset(); + let dt_fixed = + TimeZone::from_local_datetime(&local_offset, &combined) + .single() + .unwrap_or_default(); return Value::date(dt_fixed, span); } ParseResult::DateTime(date) => { @@ -289,10 +290,11 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value { ParseResult::Time(time) => { let date = Local::now().date_naive(); let combined = date.and_time(time); - let dt_fixed = DateTime::from_naive_utc_and_offset( - combined, - *Local::now().offset(), - ); + let local_offset = *Local::now().offset(); + let dt_fixed = + TimeZone::from_local_datetime(&local_offset, &combined) + .single() + .unwrap_or_default(); return Value::date(dt_fixed, span); } } @@ -386,13 +388,15 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value { Ok(d) => Value::date ( d, head ), Err(reason) => { match NaiveDateTime::parse_from_str(val, &dt.0) { - Ok(d) => Value::date ( - DateTime::from_naive_utc_and_offset( - d, - *Local::now().offset(), - ), - head, - ), + Ok(d) => { + let local_offset = *Local::now().offset(); + let dt_fixed = + TimeZone::from_local_datetime(&local_offset, &d) + .single() + .unwrap_or_default(); + + Value::date (dt_fixed,head) + } Err(_) => { Value::error ( ShellError::CantConvert { to_type: format!("could not parse as datetime using format '{}'", dt.0), from_type: reason.to_string(), span: head, help: Some("you can use `into datetime` without a format string to enable flexible parsing".to_string()) },