Skip to content

Commit

Permalink
date: Adds support datetime for parameter -d
Browse files Browse the repository at this point in the history
This resolved issue uutils#5177.

The PR adds a new enum  HumanDuration(Duration), HumanDateTime(DateTime<FixedOffset>) and uses  parse_datetime::parse_datetime::from_str  to support datetime if relative time cannot be parsed.

Furthermore tests are added for tests/by-util/test_date.rs.
  • Loading branch information
philolo1 authored and sylvestre committed Sep 23, 2023
1 parent ba3f266 commit f95e42a
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 24 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ num-traits = "0.2.16"
number_prefix = "0.4"
once_cell = "1.18.0"
onig = { version = "~6.4", default-features = false }
parse_datetime = "0.4.0"
parse_datetime = "0.5.0"
phf = "0.11.2"
phf_codegen = "0.11.2"
platform-info = "2.0.2"
Expand Down
26 changes: 6 additions & 20 deletions src/uu/date/src/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ enum DateSource {
Now,
Custom(String),
File(PathBuf),
Human(Duration),
Human(DateTime<FixedOffset>),
}

enum Iso8601Format {
Expand Down Expand Up @@ -166,8 +166,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
};

let date_source = if let Some(date) = matches.get_one::<String>(OPT_DATE) {
if let Ok(duration) = parse_datetime::from_str(date.as_str()) {
DateSource::Human(duration)
if let Ok(datetime) = parse_datetime::parse_datetime(date.as_str()) {
DateSource::Human(datetime)
} else {
DateSource::Custom(date.into())
}
Expand Down Expand Up @@ -221,23 +221,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let iter = std::iter::once(date);
Box::new(iter)
}
DateSource::Human(relative_time) => {
// Get the current DateTime<FixedOffset> for things like "1 year ago"
let current_time = DateTime::<FixedOffset>::from(Local::now());
// double check the result is overflow or not of the current_time + relative_time
// it may cause a panic of chrono::datetime::DateTime add
match current_time.checked_add_signed(relative_time) {
Some(date) => {
let iter = std::iter::once(Ok(date));
Box::new(iter)
}
None => {
return Err(USimpleError::new(
1,
format!("invalid date {}", relative_time),
));
}
}
DateSource::Human(date) => {
let iter = std::iter::once(Ok(date));
Box::new(iter)
}
DateSource::File(ref path) => {
if path.is_dir() {
Expand Down
39 changes: 38 additions & 1 deletion tests/by-util/test_date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ fn test_unsupported_format() {
}

#[test]
fn test_date_string_human() {
fn test_date_string_human_relative_time() {
let date_formats = vec![
"1 year ago",
"1 year",
Expand All @@ -390,6 +390,43 @@ fn test_date_string_human() {
}
}

#[test]
fn test_date_string_human_date_time() {
let date_formats = vec![
// unix timestamp format
"@0",
"@2",
"@10",
"@100",
"@2000",
"@1234400000",
"@1334400000",
"@1692582913",
"@2092582910",
// format YYYY-MM-DD
"2012-01-01",
"1999-01-12",
"2012-01-12",
// format YYYY-MM-DD HH:mm
"1970-01-01 00:00",
"2000-02-29 12:34",
"2100-02-28 23:59",
"2012-12-31 05:30",
"1800-01-01 18:45",
"9999-12-31 11:11",
"2023-08-21 14:55", //
];
let re = Regex::new(r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}\n$").unwrap();
for date_format in date_formats {
new_ucmd!()
.arg("-d")
.arg(date_format)
.arg("+%Y-%m-%d %S:%M")
.succeeds()
.stdout_matches(&re);
}
}

#[test]
fn test_invalid_date_string() {
new_ucmd!()
Expand Down

0 comments on commit f95e42a

Please sign in to comment.