[fix] crashing issues when the given timestamp is out of range (#3271)

* add support for timestamp-based time conversion by specifing timezone or 'UTC/Local'

* [fix] fix the wrong test sample

* code formating

* code formating and import missing mod to test

* code formating again

* [fix] it won't crash when given timestamp is too big.

* [fix] code formatting =_=b
This commit is contained in:
ChroniCat 2021-04-06 20:22:07 +08:00 committed by GitHub
parent dc8a68c98f
commit ad1c4f5e39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -110,13 +110,13 @@ impl WholeStreamCommand for SubCommand {
result: None, result: None,
}, },
Example { Example {
description: "Convert to datetime using a specified timezone", description: "Convert timestamp (no larger than 8e+12) to datetime using a specified timezone",
example: "echo '1614434140' | str to-datetime -z 'UTC'", example: "echo '1614434140' | str to-datetime -z 'UTC'",
result: None, result: None,
}, },
Example { Example {
description: description:
"Convert to datetime using a specified timezone offset (between -12 and 12)", "Convert timestamp (no larger than 8e+12) to datetime using a specified timezone offset (between -12 and 12)",
example: "echo '1614434140' | str to-datetime -o '+9'", example: "echo '1614434140' | str to-datetime -o '+9'",
result: None, result: None,
}, },
@ -203,7 +203,17 @@ fn action(
let ts = s.parse::<i64>(); let ts = s.parse::<i64>();
// if timezone if specified, first check if the input is a timestamp. // if timezone if specified, first check if the input is a timestamp.
if let Some(tz) = timezone { if let Some(tz) = timezone {
const TIMESTAMP_BOUND: i64 = 8.2e+12 as i64;
// Since the timestamp method of chrono itself don't throw an error (it just panicked)
// We have to manually guard it.
if let Ok(t) = ts { if let Ok(t) = ts {
if t.abs() > TIMESTAMP_BOUND {
return Err(ShellError::labeled_error(
"could not parse input as a valid timestamp",
"given timestamp is out of range, it should between -8e+12 and 8e+12",
tag.into().span,
));
}
const HOUR: i32 = 3600; const HOUR: i32 = 3600;
let stampout = match tz.item { let stampout = match tz.item {
Zone::Utc => UntaggedValue::date(Utc.timestamp(t, 0)), Zone::Utc => UntaggedValue::date(Utc.timestamp(t, 0)),
@ -347,6 +357,18 @@ mod tests {
} }
} }
#[test]
fn takes_invalid_timestamp() {
let date_str = string("10440970000000");
let timezone_option = Some(Tagged {
item: Zone::Utc,
tag: Tag::unknown(),
});
let actual = action(&date_str, &timezone_option, &None, Tag::unknown());
assert!(actual.is_err());
}
#[test] #[test]
fn communicates_parsing_error_given_an_invalid_datetimelike_string() { fn communicates_parsing_error_given_an_invalid_datetimelike_string() {
let date_str = string("16.11.1984 8:00 am Oops0000"); let date_str = string("16.11.1984 8:00 am Oops0000");