diff --git a/crates/nu-command/src/conversions/into/duration.rs b/crates/nu-command/src/conversions/into/duration.rs index f2812c9b70..31e2b02ceb 100644 --- a/crates/nu-command/src/conversions/into/duration.rs +++ b/crates/nu-command/src/conversions/into/duration.rs @@ -114,14 +114,21 @@ impl Command for SubCommand { }), }, Example { - description: "Convert string to a named duration", + description: "Convert string to the requested duration as a string", example: "'7min' | into duration --convert sec", result: Some(Value::String { val: "420 sec".to_string(), span, }), }, - + Example { + description: "Convert duration to the requested duration as a string", + example: "420sec | into duration --convert min", + result: Some(Value::String { + val: "7 min".to_string(), + span, + }), + }, ] } } @@ -135,18 +142,20 @@ fn into_duration( let head = call.head; let convert_to_unit: Option> = call.get_flag(engine_state, stack, "convert")?; let column_paths: Vec = call.rest(engine_state, stack, 0)?; + let config = engine_state.get_config(); + let float_precision = config.float_precision as usize; input.map( move |v| { if column_paths.is_empty() { - action(&v, &convert_to_unit, head) + action(&v, &convert_to_unit, float_precision, head) } else { let mut ret = v; for path in &column_paths { let d = convert_to_unit.clone(); let r = ret.update_cell_path( &path.members, - Box::new(move |old| action(old, &d, head)), + Box::new(move |old| action(old, &d, float_precision, head)), ); if let Err(error) = r { return Value::Error { error }; @@ -166,127 +175,129 @@ fn convert_str_from_unit_to_unit( to_unit: &str, span: Span, value_span: Span, -) -> Result { +) -> Result { match (from_unit, to_unit) { - ("ns", "ns") => Ok(val), - ("ns", "us") => Ok(val / 1000), - ("ns", "ms") => Ok(val / 1000 / 1000), - ("ns", "sec") => Ok(val / 1000 / 1000 / 1000), - ("ns", "min") => Ok(val / 1000 / 1000 / 1000 / 60), - ("ns", "hr") => Ok(val / 1000 / 1000 / 1000 / 60 / 60), - ("ns", "day") => Ok(val / 1000 / 1000 / 1000 / 60 / 60 / 24), - ("ns", "wk") => Ok(val / 1000 / 1000 / 1000 / 60 / 60 / 24 / 7), - ("ns", "month") => Ok(val / 1000 / 1000 / 1000 / 60 / 60 / 24 / 30), - ("ns", "yr") => Ok(val / 1000 / 1000 / 1000 / 60 / 60 / 24 / 365), - ("ns", "dec") => Ok(val / 10 / 1000 / 1000 / 1000 / 60 / 60 / 24 / 365), + ("ns", "ns") => Ok(val as f64), + ("ns", "us") => Ok(val as f64 / 1000.0), + ("ns", "ms") => Ok(val as f64 / 1000.0 / 1000.0), + ("ns", "sec") => Ok(val as f64 / 1000.0 / 1000.0 / 1000.0), + ("ns", "min") => Ok(val as f64 / 1000.0 / 1000.0 / 1000.0 / 60.0), + ("ns", "hr") => Ok(val as f64 / 1000.0 / 1000.0 / 1000.0 / 60.0 / 60.0), + ("ns", "day") => Ok(val as f64 / 1000.0 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0), + ("ns", "wk") => Ok(val as f64 / 1000.0 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0 / 7.0), + ("ns", "month") => Ok(val as f64 / 1000.0 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0 / 30.0), + ("ns", "yr") => Ok(val as f64 / 1000.0 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0 / 365.0), + ("ns", "dec") => { + Ok(val as f64 / 10.0 / 1000.0 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0 / 365.0) + } - ("us", "ns") => Ok(val * 1000), - ("us", "us") => Ok(val), - ("us", "ms") => Ok(val / 1000), - ("us", "sec") => Ok(val / 1000 / 1000), - ("us", "min") => Ok(val / 1000 / 1000 / 60), - ("us", "hr") => Ok(val / 1000 / 1000 / 60 / 60), - ("us", "day") => Ok(val / 1000 / 1000 / 60 / 60 / 24), - ("us", "wk") => Ok(val / 1000 / 1000 / 60 / 60 / 24 / 7), - ("us", "month") => Ok(val / 1000 / 1000 / 60 / 60 / 24 / 30), - ("us", "yr") => Ok(val / 1000 / 1000 / 60 / 60 / 24 / 365), - ("us", "dec") => Ok(val / 10 / 1000 / 1000 / 60 / 60 / 24 / 365), + ("us", "ns") => Ok(val as f64 * 1000.0), + ("us", "us") => Ok(val as f64), + ("us", "ms") => Ok(val as f64 / 1000.0), + ("us", "sec") => Ok(val as f64 / 1000.0 / 1000.0), + ("us", "min") => Ok(val as f64 / 1000.0 / 1000.0 / 60.0), + ("us", "hr") => Ok(val as f64 / 1000.0 / 1000.0 / 60.0 / 60.0), + ("us", "day") => Ok(val as f64 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0), + ("us", "wk") => Ok(val as f64 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0 / 7.0), + ("us", "month") => Ok(val as f64 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0 / 30.0), + ("us", "yr") => Ok(val as f64 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0 / 365.0), + ("us", "dec") => Ok(val as f64 / 10.0 / 1000.0 / 1000.0 / 60.0 / 60.0 / 24.0 / 365.0), - ("ms", "ns") => Ok(val * 1000 * 1000), - ("ms", "us") => Ok(val * 1000), - ("ms", "ms") => Ok(val), - ("ms", "sec") => Ok(val / 1000), - ("ms", "min") => Ok(val / 1000 / 60), - ("ms", "hr") => Ok(val / 1000 / 60 / 60), - ("ms", "day") => Ok(val / 1000 / 60 / 60 / 24), - ("ms", "wk") => Ok(val / 1000 / 60 / 60 / 24 / 7), - ("ms", "month") => Ok(val / 1000 / 60 / 60 / 24 / 30), - ("ms", "yr") => Ok(val / 1000 / 60 / 60 / 24 / 365), - ("ms", "dec") => Ok(val / 10 / 1000 / 60 / 60 / 24 / 365), + ("ms", "ns") => Ok(val as f64 * 1000.0 * 1000.0), + ("ms", "us") => Ok(val as f64 * 1000.0), + ("ms", "ms") => Ok(val as f64), + ("ms", "sec") => Ok(val as f64 / 1000.0), + ("ms", "min") => Ok(val as f64 / 1000.0 / 60.0), + ("ms", "hr") => Ok(val as f64 / 1000.0 / 60.0 / 60.0), + ("ms", "day") => Ok(val as f64 / 1000.0 / 60.0 / 60.0 / 24.0), + ("ms", "wk") => Ok(val as f64 / 1000.0 / 60.0 / 60.0 / 24.0 / 7.0), + ("ms", "month") => Ok(val as f64 / 1000.0 / 60.0 / 60.0 / 24.0 / 30.0), + ("ms", "yr") => Ok(val as f64 / 1000.0 / 60.0 / 60.0 / 24.0 / 365.0), + ("ms", "dec") => Ok(val as f64 / 10.0 / 1000.0 / 60.0 / 60.0 / 24.0 / 365.0), - ("sec", "ns") => Ok(val * 1000 * 1000 * 1000), - ("sec", "us") => Ok(val * 1000 * 1000), - ("sec", "ms") => Ok(val * 1000), - ("sec", "sec") => Ok(val), - ("sec", "min") => Ok(val / 60), - ("sec", "hr") => Ok(val / 60 / 60), - ("sec", "day") => Ok(val / 60 / 60 / 24), - ("sec", "wk") => Ok(val / 60 / 60 / 24 / 7), - ("sec", "month") => Ok(val / 60 / 60 / 24 / 30), - ("sec", "yr") => Ok(val / 60 / 60 / 24 / 365), - ("sec", "dec") => Ok(val / 10 / 60 / 60 / 24 / 365), + ("sec", "ns") => Ok(val as f64 * 1000.0 * 1000.0 * 1000.0), + ("sec", "us") => Ok(val as f64 * 1000.0 * 1000.0), + ("sec", "ms") => Ok(val as f64 * 1000.0), + ("sec", "sec") => Ok(val as f64), + ("sec", "min") => Ok(val as f64 / 60.0), + ("sec", "hr") => Ok(val as f64 / 60.0 / 60.0), + ("sec", "day") => Ok(val as f64 / 60.0 / 60.0 / 24.0), + ("sec", "wk") => Ok(val as f64 / 60.0 / 60.0 / 24.0 / 7.0), + ("sec", "month") => Ok(val as f64 / 60.0 / 60.0 / 24.0 / 30.0), + ("sec", "yr") => Ok(val as f64 / 60.0 / 60.0 / 24.0 / 365.0), + ("sec", "dec") => Ok(val as f64 / 10.0 / 60.0 / 60.0 / 24.0 / 365.0), - ("min", "ns") => Ok(val * 1000 * 1000 * 1000 * 60), - ("min", "us") => Ok(val * 1000 * 1000 * 60), - ("min", "ms") => Ok(val * 1000 * 60), - ("min", "sec") => Ok(val * 60), - ("min", "min") => Ok(val), - ("min", "hr") => Ok(val / 60), - ("min", "day") => Ok(val / 60 / 24), - ("min", "wk") => Ok(val / 60 / 24 / 7), - ("min", "month") => Ok(val / 60 / 24 / 30), - ("min", "yr") => Ok(val / 60 / 24 / 365), - ("min", "dec") => Ok(val / 10 / 60 / 24 / 365), + ("min", "ns") => Ok(val as f64 * 1000.0 * 1000.0 * 1000.0 * 60.0), + ("min", "us") => Ok(val as f64 * 1000.0 * 1000.0 * 60.0), + ("min", "ms") => Ok(val as f64 * 1000.0 * 60.0), + ("min", "sec") => Ok(val as f64 * 60.0), + ("min", "min") => Ok(val as f64), + ("min", "hr") => Ok(val as f64 / 60.0), + ("min", "day") => Ok(val as f64 / 60.0 / 24.0), + ("min", "wk") => Ok(val as f64 / 60.0 / 24.0 / 7.0), + ("min", "month") => Ok(val as f64 / 60.0 / 24.0 / 30.0), + ("min", "yr") => Ok(val as f64 / 60.0 / 24.0 / 365.0), + ("min", "dec") => Ok(val as f64 / 10.0 / 60.0 / 24.0 / 365.0), - ("hr", "ns") => Ok(val * 1000 * 1000 * 1000 * 60 * 60), - ("hr", "us") => Ok(val * 1000 * 1000 * 60 * 60), - ("hr", "ms") => Ok(val * 1000 * 60 * 60), - ("hr", "sec") => Ok(val * 60 * 60), - ("hr", "min") => Ok(val * 60), - ("hr", "hr") => Ok(val), - ("hr", "day") => Ok(val / 24), - ("hr", "wk") => Ok(val / 24 / 7), - ("hr", "month") => Ok(val / 24 / 30), - ("hr", "yr") => Ok(val / 24 / 365), - ("hr", "dec") => Ok(val / 10 / 24 / 365), + ("hr", "ns") => Ok(val as f64 * 1000.0 * 1000.0 * 1000.0 * 60.0 * 60.0), + ("hr", "us") => Ok(val as f64 * 1000.0 * 1000.0 * 60.0 * 60.0), + ("hr", "ms") => Ok(val as f64 * 1000.0 * 60.0 * 60.0), + ("hr", "sec") => Ok(val as f64 * 60.0 * 60.0), + ("hr", "min") => Ok(val as f64 * 60.0), + ("hr", "hr") => Ok(val as f64), + ("hr", "day") => Ok(val as f64 / 24.0), + ("hr", "wk") => Ok(val as f64 / 24.0 / 7.0), + ("hr", "month") => Ok(val as f64 / 24.0 / 30.0), + ("hr", "yr") => Ok(val as f64 / 24.0 / 365.0), + ("hr", "dec") => Ok(val as f64 / 10.0 / 24.0 / 365.0), - ("day", "ns") => Ok(val * 1000 * 1000 * 1000 * 60 * 60 * 24), - ("day", "us") => Ok(val * 1000 * 1000 * 60 * 60 * 24), - ("day", "ms") => Ok(val * 1000 * 60 * 60 * 24), - ("day", "sec") => Ok(val * 60 * 60 * 24), - ("day", "min") => Ok(val * 60 * 24), - ("day", "hr") => Ok(val * 24), - ("day", "day") => Ok(val), - ("day", "wk") => Ok(val / 7), - ("day", "month") => Ok(val / 30), - ("day", "yr") => Ok(val / 365), - ("day", "dec") => Ok(val / 10 / 365), + ("day", "ns") => Ok(val as f64 * 1000.0 * 1000.0 * 1000.0 * 60.0 * 60.0 * 24.0), + ("day", "us") => Ok(val as f64 * 1000.0 * 1000.0 * 60.0 * 60.0 * 24.0), + ("day", "ms") => Ok(val as f64 * 1000.0 * 60.0 * 60.0 * 24.0), + ("day", "sec") => Ok(val as f64 * 60.0 * 60.0 * 24.0), + ("day", "min") => Ok(val as f64 * 60.0 * 24.0), + ("day", "hr") => Ok(val as f64 * 24.0), + ("day", "day") => Ok(val as f64), + ("day", "wk") => Ok(val as f64 / 7.0), + ("day", "month") => Ok(val as f64 / 30.0), + ("day", "yr") => Ok(val as f64 / 365.0), + ("day", "dec") => Ok(val as f64 / 10.0 / 365.0), - ("wk", "ns") => Ok(val * 1000 * 1000 * 1000 * 60 * 60 * 24 * 7), - ("wk", "us") => Ok(val * 1000 * 1000 * 60 * 60 * 24 * 7), - ("wk", "ms") => Ok(val * 1000 * 60 * 60 * 24 * 7), - ("wk", "sec") => Ok(val * 60 * 60 * 24 * 7), - ("wk", "min") => Ok(val * 60 * 24 * 7), - ("wk", "hr") => Ok(val * 24 * 7), - ("wk", "day") => Ok(val * 7), - ("wk", "wk") => Ok(val), - ("wk", "month") => Ok(val / 4), - ("wk", "yr") => Ok(val / 52), - ("wk", "dec") => Ok(val / 10 / 52), + ("wk", "ns") => Ok(val as f64 * 1000.0 * 1000.0 * 1000.0 * 60.0 * 60.0 * 24.0 * 7.0), + ("wk", "us") => Ok(val as f64 * 1000.0 * 1000.0 * 60.0 * 60.0 * 24.0 * 7.0), + ("wk", "ms") => Ok(val as f64 * 1000.0 * 60.0 * 60.0 * 24.0 * 7.0), + ("wk", "sec") => Ok(val as f64 * 60.0 * 60.0 * 24.0 * 7.0), + ("wk", "min") => Ok(val as f64 * 60.0 * 24.0 * 7.0), + ("wk", "hr") => Ok(val as f64 * 24.0 * 7.0), + ("wk", "day") => Ok(val as f64 * 7.0), + ("wk", "wk") => Ok(val as f64), + ("wk", "month") => Ok(val as f64 / 4.0), + ("wk", "yr") => Ok(val as f64 / 52.0), + ("wk", "dec") => Ok(val as f64 / 10.0 / 52.0), - ("month", "ns") => Ok(val * 1000 * 1000 * 1000 * 60 * 60 * 24 * 30), - ("month", "us") => Ok(val * 1000 * 1000 * 60 * 60 * 24 * 30), - ("month", "ms") => Ok(val * 1000 * 60 * 60 * 24 * 30), - ("month", "sec") => Ok(val * 60 * 60 * 24 * 30), - ("month", "min") => Ok(val * 60 * 24 * 30), - ("month", "hr") => Ok(val * 24 * 30), - ("month", "day") => Ok(val * 30), - ("month", "wk") => Ok(val * 4), - ("month", "month") => Ok(val), - ("month", "yr") => Ok(val / 12), - ("month", "dec") => Ok(val / 10 / 12), + ("month", "ns") => Ok(val as f64 * 1000.0 * 1000.0 * 1000.0 * 60.0 * 60.0 * 24.0 * 30.0), + ("month", "us") => Ok(val as f64 * 1000.0 * 1000.0 * 60.0 * 60.0 * 24.0 * 30.0), + ("month", "ms") => Ok(val as f64 * 1000.0 * 60.0 * 60.0 * 24.0 * 30.0), + ("month", "sec") => Ok(val as f64 * 60.0 * 60.0 * 24.0 * 30.0), + ("month", "min") => Ok(val as f64 * 60.0 * 24.0 * 30.0), + ("month", "hr") => Ok(val as f64 * 24.0 * 30.0), + ("month", "day") => Ok(val as f64 * 30.0), + ("month", "wk") => Ok(val as f64 * 4.0), + ("month", "month") => Ok(val as f64), + ("month", "yr") => Ok(val as f64 / 12.0), + ("month", "dec") => Ok(val as f64 / 10.0 / 12.0), - ("yr", "ns") => Ok(val * 1000 * 1000 * 1000 * 60 * 60 * 24 * 365), - ("yr", "us") => Ok(val * 1000 * 1000 * 60 * 60 * 24 * 365), - ("yr", "ms") => Ok(val * 1000 * 60 * 60 * 24 * 365), - ("yr", "sec") => Ok(val * 60 * 60 * 24 * 365), - ("yr", "min") => Ok(val * 60 * 24 * 365), - ("yr", "hr") => Ok(val * 24 * 365), - ("yr", "day") => Ok(val * 365), - ("yr", "wk") => Ok(val * 52), - ("yr", "month") => Ok(val * 12), - ("yr", "yr") => Ok(val), - ("yr", "dec") => Ok(val / 10), + ("yr", "ns") => Ok(val as f64 * 1000.0 * 1000.0 * 1000.0 * 60.0 * 60.0 * 24.0 * 365.0), + ("yr", "us") => Ok(val as f64 * 1000.0 * 1000.0 * 60.0 * 60.0 * 24.0 * 365.0), + ("yr", "ms") => Ok(val as f64 * 1000.0 * 60.0 * 60.0 * 24.0 * 365.0), + ("yr", "sec") => Ok(val as f64 * 60.0 * 60.0 * 24.0 * 365.0), + ("yr", "min") => Ok(val as f64 * 60.0 * 24.0 * 365.0), + ("yr", "hr") => Ok(val as f64 * 24.0 * 365.0), + ("yr", "day") => Ok(val as f64 * 365.0), + ("yr", "wk") => Ok(val as f64 * 52.0), + ("yr", "month") => Ok(val as f64 * 12.0), + ("yr", "yr") => Ok(val as f64), + ("yr", "dec") => Ok(val as f64 / 10.0), _ => Err(ShellError::CantConvertWithValue( "string duration".to_string(), @@ -369,19 +380,41 @@ fn string_to_unit_duration( )) } -fn action(input: &Value, convert_to_unit: &Option>, span: Span) -> Value { +fn action( + input: &Value, + convert_to_unit: &Option>, + float_precision: usize, + span: Span, +) -> Value { match input { Value::Duration { - val: _val_num, - span: _value_span, + val: val_num, + span: value_span, } => { - if let Some(_to_unit) = convert_to_unit { - Value::Error { - error: ShellError::UnsupportedInput( - "Cannot convert from a Value::Duration right now. Try making it a string." - .into(), - span, - ), + if let Some(to_unit) = convert_to_unit { + let from_unit = "ns"; + let duration = *val_num; + match convert_str_from_unit_to_unit( + duration, + from_unit, + &to_unit.item, + span, + *value_span, + ) { + Ok(d) => { + if d.fract() == 0.0 { + Value::String { + val: format!("{} {}", d, &to_unit.item), + span: *value_span, + } + } else { + Value::String { + val: format!("{:.float_precision$} {}", d, &to_unit.item), + span: *value_span, + } + } + } + Err(e) => Value::Error { error: e }, } } else { input.clone() @@ -402,10 +435,19 @@ fn action(input: &Value, convert_to_unit: &Option>, span: Span) span, *value_span, ) { - Ok(d) => Value::String { - val: format!("{} {}", d, &to_unit.item), - span: *value_span, - }, + Ok(d) => { + if d.fract() == 0.0 { + Value::String { + val: format!("{} {}", d, &to_unit.item), + span: *value_span, + } + } else { + Value::String { + val: format!("{:.float_precision$} {}", d, &to_unit.item), + span: *value_span, + } + } + } Err(e) => Value::Error { error: e }, } } else { @@ -450,7 +492,7 @@ mod test { let expected = Value::Duration { val: 3, span }; let convert_duration = None; - let actual = action(&word, &convert_duration, span); + let actual = action(&word, &convert_duration, 2, span); assert_eq!(actual, expected); } @@ -464,7 +506,7 @@ mod test { }; let convert_duration = None; - let actual = action(&word, &convert_duration, span); + let actual = action(&word, &convert_duration, 2, span); assert_eq!(actual, expected); } @@ -478,7 +520,7 @@ mod test { }; let convert_duration = None; - let actual = action(&word, &convert_duration, span); + let actual = action(&word, &convert_duration, 2, span); assert_eq!(actual, expected); } @@ -492,7 +534,7 @@ mod test { }; let convert_duration = None; - let actual = action(&word, &convert_duration, span); + let actual = action(&word, &convert_duration, 2, span); assert_eq!(actual, expected); } @@ -506,7 +548,7 @@ mod test { }; let convert_duration = None; - let actual = action(&word, &convert_duration, span); + let actual = action(&word, &convert_duration, 2, span); assert_eq!(actual, expected); } @@ -520,7 +562,7 @@ mod test { }; let convert_duration = None; - let actual = action(&word, &convert_duration, span); + let actual = action(&word, &convert_duration, 2, span); assert_eq!(actual, expected); } @@ -534,7 +576,7 @@ mod test { }; let convert_duration = None; - let actual = action(&word, &convert_duration, span); + let actual = action(&word, &convert_duration, 2, span); assert_eq!(actual, expected); } @@ -548,7 +590,7 @@ mod test { }; let convert_duration = None; - let actual = action(&word, &convert_duration, span); + let actual = action(&word, &convert_duration, 2, span); assert_eq!(actual, expected); } }