mirror of
https://github.com/nushell/nushell.git
synced 2025-05-02 17:14:27 +02:00
feat: into duration accepts floats (#15297)
Issue #9887 which can be closed after this is merged. # Description This allows the "into duration" command to accept floats as inputs. Examples: <img width="767" alt="image" src="https://github.com/user-attachments/assets/da181f2a-7ad6-4efb-a6db-f9c6d8929c71" /> <img width="710" alt="image" src="https://github.com/user-attachments/assets/78623a39-33ad-42a0-9324-a147be86f95c" /> **How it works:** Using strings, like `"1.234sec" | into duration`, is already working, so if a user inputs `1.234 | into duration --sec`, I just convert this back to a string and use the previous conversion functions. **Limitations:** there are some limitation to using floats, but it's a general limitation that is already present for other use cases: - only 3 digits are taken into account in the decimal part - floating durations in nano seconds are always floored and not rounded <img width="761" alt="image" src="https://github.com/user-attachments/assets/a9076aab-da03-43f2-927c-c9703fc4f955" /> # User-Facing Changes Users can inject floats with `into duration` # Tests + Formatting cargo fmt and clippy OK Tests OK # After Submitting The example I added will automatically become part of the doc, I think that's enough for documentation.
This commit is contained in:
parent
df74a0c961
commit
67b6188b19
@ -15,6 +15,7 @@ impl Command for IntoDuration {
|
||||
Signature::build("into duration")
|
||||
.input_output_types(vec![
|
||||
(Type::Int, Type::Duration),
|
||||
(Type::Float, Type::Duration),
|
||||
(Type::String, Type::Duration),
|
||||
(Type::Duration, Type::Duration),
|
||||
(Type::table(), Type::table()),
|
||||
@ -109,6 +110,11 @@ impl Command for IntoDuration {
|
||||
example: "1_234 | into duration --unit ms",
|
||||
result: Some(Value::test_duration(1_234 * 1_000_000)),
|
||||
},
|
||||
Example {
|
||||
description: "Convert a floating point number of an arbitrary unit to duration",
|
||||
example: "1.234 | into duration --unit sec",
|
||||
result: Some(Value::test_duration(1_234 * 1_000_000)),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -236,22 +242,22 @@ fn action(input: &Value, unit: &str, span: Span) -> Value {
|
||||
let value_span = input.span();
|
||||
match input {
|
||||
Value::Duration { .. } => input.clone(),
|
||||
Value::String { val, .. } => match compound_to_duration(val, value_span) {
|
||||
Value::String { val, .. } => {
|
||||
if let Ok(num) = val.parse::<f64>() {
|
||||
let ns = unit_to_ns_factor(unit);
|
||||
return Value::duration((num * (ns as f64)) as i64, span);
|
||||
}
|
||||
match compound_to_duration(val, value_span) {
|
||||
Ok(val) => Value::duration(val, span),
|
||||
Err(error) => Value::error(error, span),
|
||||
},
|
||||
}
|
||||
}
|
||||
Value::Float { val, .. } => {
|
||||
let ns = unit_to_ns_factor(unit);
|
||||
Value::duration((*val * (ns as f64)) as i64, span)
|
||||
}
|
||||
Value::Int { val, .. } => {
|
||||
let ns = match unit {
|
||||
"ns" => 1,
|
||||
"us" | "µs" => 1_000,
|
||||
"ms" => 1_000_000,
|
||||
"sec" => NS_PER_SEC,
|
||||
"min" => NS_PER_SEC * 60,
|
||||
"hr" => NS_PER_SEC * 60 * 60,
|
||||
"day" => NS_PER_SEC * 60 * 60 * 24,
|
||||
"wk" => NS_PER_SEC * 60 * 60 * 24 * 7,
|
||||
_ => 0,
|
||||
};
|
||||
let ns = unit_to_ns_factor(unit);
|
||||
Value::duration(*val * ns, span)
|
||||
}
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
@ -268,6 +274,20 @@ fn action(input: &Value, unit: &str, span: Span) -> Value {
|
||||
}
|
||||
}
|
||||
|
||||
fn unit_to_ns_factor(unit: &str) -> i64 {
|
||||
match unit {
|
||||
"ns" => 1,
|
||||
"us" | "µs" => 1_000,
|
||||
"ms" => 1_000_000,
|
||||
"sec" => NS_PER_SEC,
|
||||
"min" => NS_PER_SEC * 60,
|
||||
"hr" => NS_PER_SEC * 60 * 60,
|
||||
"day" => NS_PER_SEC * 60 * 60 * 24,
|
||||
"wk" => NS_PER_SEC * 60 * 60 * 24 * 7,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
Loading…
Reference in New Issue
Block a user