Repository: sharkdp/fd
File: src/filter/time.rs (Rust)

Code before:
use chrono::{DateTime, Local, NaiveDate, NaiveDateTime};
use jiff::Span;

use std::time::{Duration, SystemTime};

/// Filter based on time ranges.
#[derive(Debug, PartialEq, Eq)]
pub enum TimeFilter {
    Before(SystemTime),
    After(SystemTime),
}

impl TimeFilter {
    fn from_str(ref_time: &SystemTime, s: &str) -> Option<SystemTime> {
        s.parse::<Span>()
            .and_then(Duration::try_from)
            .map(|duration| *ref_time - duration)
            .ok()
            .or_else(|| {
                DateTime::parse_from_rfc3339(s)
                    .map(|dt| dt.into())
                    .ok()
                    .or_else(|| {
                        NaiveDate::parse_from_str(s, "%F")
                            .ok()?
                            .and_hms_opt(0, 0, 0)?
                            .and_local_timezone(Local)
                            .latest()
                    })
                    .or_else(|| {
                        NaiveDateTime::parse_from_str(s, "%F %T")
                            .ok()?
                            .and_local_timezone(Local)
                            .latest()
                    })
                    .or_else(|| {
                        let timestamp_secs = s.strip_prefix('@')?.parse().ok()?;
                        DateTime::from_timestamp(timestamp_secs, 0).map(Into::into)
                    })
                    .map(|dt| dt.into())
            })

Review comment (suggestion):
This is going to result in errors if the duration contains calendar units (years, months, weeks or days).

Looking at this code holistically, it would be better to do arithmetic using the `jiff::Span` itself with a `jiff::Zoned` (which you can get via `Zoned::try_from(*ref_time)`). And you might as well replace the `chrono` code below with Jiff. But IDK how much that snowballs into a bigger change.

Code after:
use jiff::{civil::DateTime, tz::TimeZone, Span, Timestamp, Zoned};

use std::time::SystemTime;

/// Filter based on time ranges.
#[derive(Debug, PartialEq, Eq)]
pub enum TimeFilter {
    Before(SystemTime),
    After(SystemTime),
}

impl TimeFilter {
    fn from_str(ref_time: &SystemTime, s: &str) -> Option<SystemTime> {
        s.parse::<Span>()
            .and_then(|duration| {
                Zoned::try_from(*ref_time).and_then(|zdt| zdt.checked_sub(duration))
            })
            .ok()
            .or_else(|| {
                let local_tz = TimeZone::system();
                s.parse::<Timestamp>()
                    .map(|ts| ts.to_zoned(TimeZone::UTC))
                    .ok()
                    .or_else(|| {
                        s.parse::<DateTime>()
                            .map(|dt| local_tz.to_ambiguous_zoned(dt))
                            .and_then(|zdt| zdt.later())
                            .ok()
                    })
                    .or_else(|| {
                        let timestamp_secs = s.strip_prefix('@')?.parse().ok()?;
                        Timestamp::from_second(timestamp_secs)
                            .map(|ts| ts.to_zoned(TimeZone::UTC))
                            .ok()
                    })
            })
            .map(SystemTime::from)
    }

    pub fn before(ref_time: &SystemTime, s: &str) -> Option<TimeFilter> {
        TimeFilter::from_str(ref_time, s).map(TimeFilter::Before)