expand durations to include month, year, decade (#6123)

* expand durations to include month, year, decade

* remove commented out fn

* oops, found more debug comments

* tweaked tests for the new way, borrowed heavily from chrono-humanize-rs

* clippy

* grammar
This commit is contained in:
Darren Schroeder
2022-07-26 08:05:37 -05:00
committed by GitHub
parent f5856b0914
commit d856ac92f4
7 changed files with 339 additions and 50 deletions

View File

@ -28,6 +28,10 @@ impl Command for SubCommand {
"Convert value to duration"
}
fn extra_usage(&self) -> &str {
"into duration does not take leap years into account and every month is calculated with 30 days"
}
fn search_terms(&self) -> Vec<&str> {
vec!["convert", "time", "period"]
}
@ -149,6 +153,9 @@ fn string_to_duration(s: &str, span: Span, value_span: Span) -> Result<i64, Shel
Unit::Hour => return Ok(x * 60 * 60 * 1000 * 1000 * 1000),
Unit::Day => return Ok(x * 24 * 60 * 60 * 1000 * 1000 * 1000),
Unit::Week => return Ok(x * 7 * 24 * 60 * 60 * 1000 * 1000 * 1000),
Unit::Month => return Ok(x * 30 * 24 * 60 * 60 * 1000 * 1000 * 1000), //30 days to a month
Unit::Year => return Ok(x * 365 * 24 * 60 * 60 * 1000 * 1000 * 1000), //365 days to a year
Unit::Decade => return Ok(x * 10 * 365 * 24 * 60 * 60 * 1000 * 1000 * 1000), //365 days to a year
_ => {}
}
}

View File

@ -442,6 +442,14 @@ fn convert_to_value(
val: size * 1000 * 1000 * 1000 * 1000 * 1000,
span,
}),
Unit::Exabyte => Ok(Value::Filesize {
val: size * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
span,
}),
Unit::Zettabyte => Ok(Value::Filesize {
val: size * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
span,
}),
Unit::Kibibyte => Ok(Value::Filesize {
val: size * 1024,
@ -463,6 +471,14 @@ fn convert_to_value(
val: size * 1024 * 1024 * 1024 * 1024 * 1024,
span,
}),
Unit::Exbibyte => Ok(Value::Filesize {
val: size * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
span,
}),
Unit::Zebibyte => Ok(Value::Filesize {
val: size * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
span,
}),
Unit::Nanosecond => Ok(Value::Duration { val: size, span }),
Unit::Microsecond => Ok(Value::Duration {
@ -489,8 +505,8 @@ fn convert_to_value(
Some(val) => Ok(Value::Duration { val, span }),
None => Err(ShellError::OutsideSpannedLabeledError(
original_text.to_string(),
"duration too large".into(),
"duration too large".into(),
"day duration too large".into(),
"day duration too large".into(),
expr.span,
)),
},
@ -499,11 +515,40 @@ fn convert_to_value(
Some(val) => Ok(Value::Duration { val, span }),
None => Err(ShellError::OutsideSpannedLabeledError(
original_text.to_string(),
"duration too large".into(),
"duration too large".into(),
"week duration too large".into(),
"week duration too large".into(),
expr.span,
)),
},
Unit::Month => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24 * 30) {
Some(val) => Ok(Value::Duration { val, span }),
None => Err(ShellError::OutsideSpannedLabeledError(
original_text.to_string(),
"month duration too large".into(),
"month duration too large".into(),
expr.span,
)),
},
Unit::Year => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24 * 365) {
Some(val) => Ok(Value::Duration { val, span }),
None => Err(ShellError::OutsideSpannedLabeledError(
original_text.to_string(),
"year duration too large".into(),
"year duration too large".into(),
expr.span,
)),
},
Unit::Decade => {
match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24 * 365 * 10) {
Some(val) => Ok(Value::Duration { val, span }),
None => Err(ShellError::OutsideSpannedLabeledError(
original_text.to_string(),
"decade duration too large".into(),
"decade duration too large".into(),
expr.span,
)),
}
}
}
}
Expr::Var(..) => Err(ShellError::OutsideSpannedLabeledError(

View File

@ -291,7 +291,7 @@ fn duration_math() {
"#
));
assert_eq!(actual.out, "8day");
assert_eq!(actual.out, "1wk 1day");
}
#[test]
@ -315,7 +315,7 @@ fn duration_math_with_nanoseconds() {
"#
));
assert_eq!(actual.out, "7day 10ns");
assert_eq!(actual.out, "1wk 10ns");
}
#[test]
@ -327,7 +327,22 @@ fn duration_decimal_math_with_nanoseconds() {
"#
));
assert_eq!(actual.out, "10day 10ns");
assert_eq!(actual.out, "1wk 3day 10ns");
}
#[test]
fn duration_decimal_math_with_all_units() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
5dec + 3yr + 2month + 1wk + 3day + 8hr + 10min + 16sec + 121ms + 11us + 12ns
"#
));
assert_eq!(
actual.out,
"53yr 2month 1wk 3day 8hr 10min 16sec 121ms 11µs 12ns"
);
}
#[test]