mirror of
https://github.com/uutils/coreutils
synced 2024-12-13 14:52:41 +00:00
touch: add support for some relative times
For example, $ touch -d +1 days Fixes #3964.
This commit is contained in:
parent
e307f624e8
commit
a396ebd883
3 changed files with 148 additions and 1 deletions
|
@ -198,6 +198,7 @@ pub fn uu_app() -> Command {
|
||||||
Arg::new(options::sources::DATE)
|
Arg::new(options::sources::DATE)
|
||||||
.short('d')
|
.short('d')
|
||||||
.long(options::sources::DATE)
|
.long(options::sources::DATE)
|
||||||
|
.allow_hyphen_values(true)
|
||||||
.help("parse argument and use it instead of current time")
|
.help("parse argument and use it instead of current time")
|
||||||
.value_name("STRING"),
|
.value_name("STRING"),
|
||||||
)
|
)
|
||||||
|
@ -381,6 +382,60 @@ fn parse_date(s: &str) -> UResult<FileTime> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Relative day, like "today", "tomorrow", or "yesterday".
|
||||||
|
match s {
|
||||||
|
"now" | "today" => {
|
||||||
|
let now_local = time::OffsetDateTime::now_local().unwrap();
|
||||||
|
return Ok(local_dt_to_filetime(now_local));
|
||||||
|
}
|
||||||
|
"tomorrow" => {
|
||||||
|
let duration = time::Duration::days(1);
|
||||||
|
let now_local = time::OffsetDateTime::now_local().unwrap();
|
||||||
|
let diff = now_local.checked_add(duration).unwrap();
|
||||||
|
return Ok(local_dt_to_filetime(diff));
|
||||||
|
}
|
||||||
|
"yesterday" => {
|
||||||
|
let duration = time::Duration::days(1);
|
||||||
|
let now_local = time::OffsetDateTime::now_local().unwrap();
|
||||||
|
let diff = now_local.checked_sub(duration).unwrap();
|
||||||
|
return Ok(local_dt_to_filetime(diff));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relative time, like "-1 hour" or "+3 days".
|
||||||
|
//
|
||||||
|
// TODO Add support for "year" and "month".
|
||||||
|
// TODO Add support for times without spaces like "-1hour".
|
||||||
|
let tokens: Vec<&str> = s.split_whitespace().collect();
|
||||||
|
let maybe_duration = match &tokens[..] {
|
||||||
|
[num_str, "fortnight" | "fortnights"] => num_str
|
||||||
|
.parse::<i64>()
|
||||||
|
.ok()
|
||||||
|
.map(|n| time::Duration::weeks(2 * n)),
|
||||||
|
["fortnight" | "fortnights"] => Some(time::Duration::weeks(2)),
|
||||||
|
[num_str, "week" | "weeks"] => num_str.parse::<i64>().ok().map(time::Duration::weeks),
|
||||||
|
["week" | "weeks"] => Some(time::Duration::weeks(1)),
|
||||||
|
[num_str, "day" | "days"] => num_str.parse::<i64>().ok().map(time::Duration::days),
|
||||||
|
["day" | "days"] => Some(time::Duration::days(1)),
|
||||||
|
[num_str, "hour" | "hours"] => num_str.parse::<i64>().ok().map(time::Duration::hours),
|
||||||
|
["hour" | "hours"] => Some(time::Duration::hours(1)),
|
||||||
|
[num_str, "minute" | "minutes" | "min" | "mins"] => {
|
||||||
|
num_str.parse::<i64>().ok().map(time::Duration::minutes)
|
||||||
|
}
|
||||||
|
["minute" | "minutes" | "min" | "mins"] => Some(time::Duration::minutes(1)),
|
||||||
|
[num_str, "second" | "seconds" | "sec" | "secs"] => {
|
||||||
|
num_str.parse::<i64>().ok().map(time::Duration::seconds)
|
||||||
|
}
|
||||||
|
["second" | "seconds" | "sec" | "secs"] => Some(time::Duration::seconds(1)),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(duration) = maybe_duration {
|
||||||
|
let now_local = time::OffsetDateTime::now_local().unwrap();
|
||||||
|
let diff = now_local.checked_add(duration).unwrap();
|
||||||
|
return Ok(local_dt_to_filetime(diff));
|
||||||
|
}
|
||||||
|
|
||||||
Err(USimpleError::new(1, format!("Unable to parse date: {}", s)))
|
Err(USimpleError::new(1, format!("Unable to parse date: {}", s)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -512,6 +512,98 @@ fn test_touch_set_date7() {
|
||||||
assert_eq!(mtime, expected);
|
assert_eq!(mtime, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test for setting the date by a relative time unit.
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_date_relative_smoke() {
|
||||||
|
// From the GNU documentation:
|
||||||
|
//
|
||||||
|
// > The unit of time displacement may be selected by the string
|
||||||
|
// > ‘year’ or ‘month’ for moving by whole years or months. These
|
||||||
|
// > are fuzzy units, as years and months are not all of equal
|
||||||
|
// > duration. More precise units are ‘fortnight’ which is worth 14
|
||||||
|
// > days, ‘week’ worth 7 days, ‘day’ worth 24 hours, ‘hour’ worth
|
||||||
|
// > 60 minutes, ‘minute’ or ‘min’ worth 60 seconds, and ‘second’ or
|
||||||
|
// > ‘sec’ worth one second. An ‘s’ suffix on these units is
|
||||||
|
// > accepted and ignored.
|
||||||
|
//
|
||||||
|
let times = [
|
||||||
|
// "-1 year", "+1 year", "-1 years", "+1 years",
|
||||||
|
// "-1 month", "+1 month", "-1 months", "+1 months",
|
||||||
|
"-1 fortnight",
|
||||||
|
"+1 fortnight",
|
||||||
|
"-1 fortnights",
|
||||||
|
"+1 fortnights",
|
||||||
|
"fortnight",
|
||||||
|
"fortnights",
|
||||||
|
"-1 week",
|
||||||
|
"+1 week",
|
||||||
|
"-1 weeks",
|
||||||
|
"+1 weeks",
|
||||||
|
"week",
|
||||||
|
"weeks",
|
||||||
|
"-1 day",
|
||||||
|
"+1 day",
|
||||||
|
"-1 days",
|
||||||
|
"+1 days",
|
||||||
|
"day",
|
||||||
|
"days",
|
||||||
|
"-1 hour",
|
||||||
|
"+1 hour",
|
||||||
|
"-1 hours",
|
||||||
|
"+1 hours",
|
||||||
|
"hour",
|
||||||
|
"hours",
|
||||||
|
"-1 minute",
|
||||||
|
"+1 minute",
|
||||||
|
"-1 minutes",
|
||||||
|
"+1 minutes",
|
||||||
|
"minute",
|
||||||
|
"minutes",
|
||||||
|
"-1 min",
|
||||||
|
"+1 min",
|
||||||
|
"-1 mins",
|
||||||
|
"+1 mins",
|
||||||
|
"min",
|
||||||
|
"mins",
|
||||||
|
"-1 second",
|
||||||
|
"+1 second",
|
||||||
|
"-1 seconds",
|
||||||
|
"+1 seconds",
|
||||||
|
"second",
|
||||||
|
"seconds",
|
||||||
|
"-1 sec",
|
||||||
|
"+1 sec",
|
||||||
|
"-1 secs",
|
||||||
|
"+1 secs",
|
||||||
|
"sec",
|
||||||
|
"secs",
|
||||||
|
];
|
||||||
|
for time in times {
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
at.touch("f");
|
||||||
|
ucmd.args(&["-d", time, "f"])
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr()
|
||||||
|
.no_stdout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// From the GNU documentation:
|
||||||
|
//
|
||||||
|
// > The string ‘tomorrow’ is worth one day in the future
|
||||||
|
// > (equivalent to ‘day’), the string ‘yesterday’ is worth one day
|
||||||
|
// > in the past (equivalent to ‘day ago’).
|
||||||
|
//
|
||||||
|
let times = ["yesterday", "tomorrow", "now"];
|
||||||
|
for time in times {
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
at.touch("f");
|
||||||
|
ucmd.args(&["-d", time, "f"])
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr()
|
||||||
|
.no_stdout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_touch_set_date_wrong_format() {
|
fn test_touch_set_date_wrong_format() {
|
||||||
let (_at, mut ucmd) = at_and_ucmd!();
|
let (_at, mut ucmd) = at_and_ucmd!();
|
||||||
|
|
|
@ -137,7 +137,7 @@ sed -i 's|sort |/usr/bin/sort |' tests/ls/hyperlink.sh tests/misc/test-N.sh
|
||||||
sed -i 's|split |/usr/bin/split |' tests/misc/factor-parallel.sh
|
sed -i 's|split |/usr/bin/split |' tests/misc/factor-parallel.sh
|
||||||
sed -i 's|id -|/usr/bin/id -|' tests/misc/runcon-no-reorder.sh
|
sed -i 's|id -|/usr/bin/id -|' tests/misc/runcon-no-reorder.sh
|
||||||
# tests/ls/abmon-align.sh - https://github.com/uutils/coreutils/issues/3505
|
# tests/ls/abmon-align.sh - https://github.com/uutils/coreutils/issues/3505
|
||||||
sed -i 's|touch |/usr/bin/touch |' tests/cp/preserve-link.sh tests/cp/reflink-perm.sh tests/ls/block-size.sh tests/mv/update.sh tests/misc/ls-time.sh tests/misc/stat-nanoseconds.sh tests/misc/time-style.sh tests/misc/test-N.sh tests/ls/abmon-align.sh
|
sed -i 's|touch |/usr/bin/touch |' tests/cp/reflink-perm.sh tests/ls/block-size.sh tests/mv/update.sh tests/misc/ls-time.sh tests/misc/stat-nanoseconds.sh tests/misc/time-style.sh tests/misc/test-N.sh tests/ls/abmon-align.sh
|
||||||
sed -i 's|ln -|/usr/bin/ln -|' tests/cp/link-deref.sh
|
sed -i 's|ln -|/usr/bin/ln -|' tests/cp/link-deref.sh
|
||||||
sed -i 's|cp |/usr/bin/cp |' tests/mv/hard-2.sh
|
sed -i 's|cp |/usr/bin/cp |' tests/mv/hard-2.sh
|
||||||
sed -i 's|paste |/usr/bin/paste |' tests/misc/od-endian.sh
|
sed -i 's|paste |/usr/bin/paste |' tests/misc/od-endian.sh
|
||||||
|
|
Loading…
Reference in a new issue