diff --git a/crates/nu-command/src/date/from_human.rs b/crates/nu-command/src/date/from_human.rs index f924b4d6d5..ff99dff064 100644 --- a/crates/nu-command/src/date/from_human.rs +++ b/crates/nu-command/src/date/from_human.rs @@ -103,19 +103,21 @@ fn helper(value: Value, head: Span) -> Value { } }; - if let Ok(date) = from_human_time(&input_val, Local::now().naive_local()) { + let now = Local::now(); + + if let Ok(date) = from_human_time(&input_val, now.naive_local()) { match date { ParseResult::Date(date) => { - let time = Local::now().time(); + let time = now.time(); let combined = date.and_time(time); - let local_offset = *Local::now().offset(); + let local_offset = *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) => { - let local_offset = *Local::now().offset(); + let local_offset = *now.offset(); let dt_fixed = match local_offset.from_local_datetime(&date) { chrono::LocalResult::Single(dt) => dt, chrono::LocalResult::Ambiguous(_, _) => { @@ -140,9 +142,9 @@ fn helper(value: Value, head: Span) -> Value { return Value::date(dt_fixed, span); } ParseResult::Time(time) => { - let date = Local::now().date_naive(); + let date = now.date_naive(); let combined = date.and_time(time); - let local_offset = *Local::now().offset(); + let local_offset = *now.offset(); let dt_fixed = TimeZone::from_local_datetime(&local_offset, &combined) .single() .unwrap_or_default(); @@ -151,19 +153,19 @@ fn helper(value: Value, head: Span) -> Value { } } - match from_human_time(&input_val, Local::now().naive_local()) { + match from_human_time(&input_val, now.naive_local()) { Ok(date) => match date { ParseResult::Date(date) => { - let time = Local::now().time(); + let time = now.time(); let combined = date.and_time(time); - let local_offset = *Local::now().offset(); + let local_offset = *now.offset(); let dt_fixed = TimeZone::from_local_datetime(&local_offset, &combined) .single() .unwrap_or_default(); Value::date(dt_fixed, span) } ParseResult::DateTime(date) => { - let local_offset = *Local::now().offset(); + let local_offset = *now.offset(); let dt_fixed = match local_offset.from_local_datetime(&date) { chrono::LocalResult::Single(dt) => dt, chrono::LocalResult::Ambiguous(_, _) => { @@ -188,9 +190,9 @@ fn helper(value: Value, head: Span) -> Value { Value::date(dt_fixed, span) } ParseResult::Time(time) => { - let date = Local::now().date_naive(); + let date = now.date_naive(); let combined = date.and_time(time); - let local_offset = *Local::now().offset(); + let local_offset = *now.offset(); let dt_fixed = TimeZone::from_local_datetime(&local_offset, &combined) .single() .unwrap_or_default(); diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index 4969daf28e..2d820b044a 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -25,7 +25,7 @@ use crate::{ engine::{Closure, EngineState}, BlockId, Config, ShellError, Signals, Span, Type, }; -use chrono::{DateTime, Datelike, FixedOffset, Locale, TimeZone}; +use chrono::{DateTime, Datelike, Duration, FixedOffset, Local, Locale, TimeZone}; use chrono_humanize::HumanTime; use fancy_regex::Regex; use nu_utils::{ @@ -953,7 +953,7 @@ impl Value { } else { val.to_rfc3339() }, - HumanTime::from(*val), + human_time_from_now(val), ) } }, @@ -999,7 +999,7 @@ impl Value { match self { Value::Date { val, .. } => match &config.datetime_format.table { Some(format) => self.format_datetime(val, format), - None => HumanTime::from(*val).to_string(), + None => human_time_from_now(val).to_string(), }, Value::List { ref vals, .. } => { if !vals.is_empty() && vals.iter().all(|x| matches!(x, Value::Record { .. })) { @@ -4017,6 +4017,15 @@ fn operator_type_error( } } +fn human_time_from_now(val: &DateTime) -> HumanTime { + let now = Local::now().with_timezone(val.offset()); + let delta = *val - now; + let delta_seconds = delta.num_nanoseconds().unwrap_or(0) as f64 / 1_000_000_000.0; + let delta_seconds_rounded = delta_seconds.round() as i64; + + HumanTime::from(Duration::seconds(delta_seconds_rounded)) +} + #[cfg(test)] mod tests { use super::{Record, Value};