diff --git a/CHANGELOG.md b/CHANGELOG.md index 08f447f..1717b85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Features - Add `dir` as an alias to `directory` when using `-t` \ `--type`, see #1460 and #1464 (@Ato2207). +- Add support for @%s date format in time filters similar to GNU date (seconds since Unix epoch for --older/--newer), see #1493 (@nabellows) ## Bugfixes diff --git a/doc/fd.1 b/doc/fd.1 index 8877317..1ac63c5 100644 --- a/doc/fd.1 +++ b/doc/fd.1 @@ -312,8 +312,9 @@ tebibytes Filter results based on the file modification time. Files with modification times greater than the argument will be returned. The argument can be provided as a duration (\fI10h, 1d, 35min\fR) or as a specific point -in time in either full RFC3339 format with time zone, or as a date or datetime in the -local time zone (\fIYYYY-MM-DD\fR or \fIYYYY-MM-DD HH:MM:SS\fR). +in time as full RFC3339 format with time zone, as a date or datetime in the +local time zone (\fIYYYY-MM-DD\fR or \fIYYYY-MM-DD HH:MM:SS\fR), or as the prefix '@' +followed by the number of seconds since the Unix epoch (@[0-9]+). \fB\-\-change-newer-than\fR, .B --newer or @@ -324,13 +325,15 @@ Examples: \-\-changed-within 2weeks \-\-change-newer-than "2018-10-27 10:00:00" \-\-newer 2018-10-27 + \-\-changed-after @1704067200 .TP .BI "\-\-changed-before " date|duration Filter results based on the file modification time. Files with modification times less than the argument will be returned. The argument can be provided as a duration (\fI10h, 1d, 35min\fR) or as a specific point -in time in either full RFC3339 format with time zone, or as a date or datetime in the -local time zone (\fIYYYY-MM-DD\fR or \fIYYYY-MM-DD HH:MM:SS\fR). +in time as full RFC3339 format with time zone, as a date or datetime in the +local time zone (\fIYYYY-MM-DD\fR or \fIYYYY-MM-DD HH:MM:SS\fR), or as the prefix '@' +followed by the number of seconds since the Unix epoch (@[0-9]+). .B --change-older-than or .B --older @@ -339,6 +342,7 @@ can be used as aliases. Examples: \-\-changed-before "2018-10-27 10:00:00" \-\-change-older-than 2weeks + \-\-older @1704067200 .TP .BI "-o, \-\-owner " [user][:group] Filter files by their user and/or group. Format: [(user|uid)][:(group|gid)]. Either side diff --git a/src/filter/time.rs b/src/filter/time.rs index 0070e5e..9631f13 100644 --- a/src/filter/time.rs +++ b/src/filter/time.rs @@ -1,4 +1,4 @@ -use chrono::{DateTime, Local, NaiveDate, NaiveDateTime}; +use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, Utc}; use std::time::SystemTime; @@ -31,6 +31,13 @@ impl TimeFilter { .and_local_timezone(Local) .latest() }) + .or_else(|| { + let timestamp_secs = s.strip_prefix('@')?.parse().ok()?; + NaiveDateTime::from_timestamp_opt(timestamp_secs, 0)? + .and_local_timezone(Utc) + .latest() + .map(Into::into) + }) .map(|dt| dt.into()) }) } @@ -135,5 +142,26 @@ mod tests { assert!(!TimeFilter::after(&ref_time, t10s_before) .unwrap() .applies_to(&t1m_ago)); + + let ref_timestamp = 1707723412u64; // Mon Feb 12 07:36:52 UTC 2024 + let ref_time = DateTime::parse_from_rfc3339("2024-02-12T07:36:52+00:00") + .unwrap() + .into(); + let t1m_ago = ref_time - Duration::from_secs(60); + let t1s_later = ref_time + Duration::from_secs(1); + // Timestamp only supported via '@' prefix + assert!(TimeFilter::before(&ref_time, &ref_timestamp.to_string()).is_none()); + assert!(TimeFilter::before(&ref_time, &format!("@{}", ref_timestamp)) + .unwrap() + .applies_to(&t1m_ago)); + assert!(!TimeFilter::before(&ref_time, &format!("@{}", ref_timestamp)) + .unwrap() + .applies_to(&t1s_later)); + assert!(!TimeFilter::after(&ref_time, &format!("@{}", ref_timestamp)) + .unwrap() + .applies_to(&t1m_ago)); + assert!(TimeFilter::after(&ref_time, &format!("@{}", ref_timestamp)) + .unwrap() + .applies_to(&t1s_later)); } }