mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
date -d supports - 1 year ago, 2 second, etc
This commit is contained in:
parent
6f0e4ece9d
commit
825d240ef0
4 changed files with 47 additions and 3 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2538,7 +2538,9 @@ version = "0.0.18"
|
|||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
"humantime_to_duration",
|
||||
"libc",
|
||||
"time",
|
||||
"uucore",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# spell-checker:ignore humantime
|
||||
[package]
|
||||
name = "uu_date"
|
||||
version = "0.0.18"
|
||||
|
@ -16,8 +17,11 @@ path = "src/date.rs"
|
|||
|
||||
[dependencies]
|
||||
chrono = { workspace=true }
|
||||
#/ TODO: check if we can avoid chrono+time
|
||||
time = { workspace=true }
|
||||
clap = { workspace=true }
|
||||
uucore = { workspace=true }
|
||||
humantime_to_duration = { workspace=true }
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = { workspace=true }
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
// spell-checker:ignore (chrono) Datelike Timelike ; (format) DATEFILE MMDDhhmm ; (vars) datetime datetimes
|
||||
// spell-checker:ignore (chrono) Datelike Timelike ; (format) DATEFILE MMDDhhmm ; (vars) datetime datetimes humantime
|
||||
|
||||
use chrono::format::{Item, StrftimeItems};
|
||||
use chrono::{DateTime, FixedOffset, Local, Offset, Utc};
|
||||
use chrono::{DateTime, Duration as ChronoDuration, FixedOffset, Local, Offset, Utc};
|
||||
#[cfg(windows)]
|
||||
use chrono::{Datelike, Timelike};
|
||||
use clap::{crate_version, Arg, ArgAction, Command};
|
||||
|
@ -18,6 +18,7 @@ use libc::{clock_settime, timespec, CLOCK_REALTIME};
|
|||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::path::PathBuf;
|
||||
use time::Duration;
|
||||
use uucore::display::Quotable;
|
||||
#[cfg(not(any(target_os = "redox")))]
|
||||
use uucore::error::FromIo;
|
||||
|
@ -96,6 +97,7 @@ enum DateSource {
|
|||
Now,
|
||||
Custom(String),
|
||||
File(PathBuf),
|
||||
Human(Duration),
|
||||
}
|
||||
|
||||
enum Iso8601Format {
|
||||
|
@ -168,7 +170,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
};
|
||||
|
||||
let date_source = if let Some(date) = matches.get_one::<String>(OPT_DATE) {
|
||||
DateSource::Custom(date.into())
|
||||
if let Ok(duration) = humantime_to_duration::from_str(date.as_str()) {
|
||||
DateSource::Human(duration)
|
||||
} else {
|
||||
DateSource::Custom(date.into())
|
||||
}
|
||||
} else if let Some(file) = matches.get_one::<String>(OPT_FILE) {
|
||||
DateSource::File(file.into())
|
||||
} else {
|
||||
|
@ -219,6 +225,15 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
let iter = std::iter::once(date);
|
||||
Box::new(iter)
|
||||
}
|
||||
DateSource::Human(ref input) => {
|
||||
// Get the current DateTime<FixedOffset> and convert the input time::Duration to chrono::Duration
|
||||
// for things like "1 year ago"
|
||||
let current_time = DateTime::<FixedOffset>::from(Local::now());
|
||||
let input_chrono = ChronoDuration::seconds(input.as_seconds_f32() as i64)
|
||||
+ ChronoDuration::nanoseconds(input.subsec_nanoseconds() as i64);
|
||||
let iter = std::iter::once(Ok(current_time + input_chrono));
|
||||
Box::new(iter)
|
||||
}
|
||||
DateSource::File(ref path) => {
|
||||
if path.is_dir() {
|
||||
return Err(USimpleError::new(
|
||||
|
|
|
@ -334,6 +334,29 @@ fn test_invalid_format_string() {
|
|||
assert!(result.stderr_str().starts_with("date: invalid format "));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_date_string_human() {
|
||||
let date_formats = vec![
|
||||
"1 year ago",
|
||||
"1 year",
|
||||
"2 months ago",
|
||||
"15 days ago",
|
||||
"1 week ago",
|
||||
"5 hours ago",
|
||||
"30 minutes ago",
|
||||
"10 seconds",
|
||||
];
|
||||
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!()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue