diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 0297a569c..5cc6983b2 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -27,7 +27,6 @@ use std::{ use std::{collections::HashSet, io::IsTerminal}; use ansi_width::ansi_width; -use chrono::format::{Item, StrftimeItems}; use chrono::{DateTime, Local, TimeDelta}; use clap::{ Arg, ArgAction, Command, @@ -274,64 +273,32 @@ enum TimeStyle { Format(String), } -/// A struct/impl used to format a file DateTime, precomputing the format for performance reasons. -struct TimeStyler { - // default format, always specified. - default: Vec>, - // format for a recent time, only specified it is is different from the default - recent: Option>>, - // If `recent` is set, cache the threshold time when we switch from recent to default format. - recent_time_threshold: Option>, +/// Whether the given date is considered recent (i.e., in the last 6 months). +fn is_recent(time: DateTime) -> bool { + // According to GNU a Gregorian year has 365.2425 * 24 * 60 * 60 == 31556952 seconds on the average. + time + TimeDelta::try_seconds(31_556_952 / 2).unwrap() > Local::now() } -impl TimeStyler { - /// Create a TimeStyler based on a TimeStyle specification. - fn new(style: &TimeStyle) -> TimeStyler { - let default: Vec> = match style { - TimeStyle::FullIso => StrftimeItems::new("%Y-%m-%d %H:%M:%S.%f %z").parse(), - TimeStyle::LongIso => StrftimeItems::new("%Y-%m-%d %H:%M").parse(), - TimeStyle::Iso => StrftimeItems::new("%Y-%m-%d ").parse(), - // In this version of chrono translating can be done - // The function is chrono::datetime::DateTime::format_localized - // However it's currently still hard to get the current pure-rust-locale - // So it's not yet implemented - TimeStyle::Locale => StrftimeItems::new("%b %e %Y").parse(), - TimeStyle::Format(fmt) => { - StrftimeItems::new_lenient(custom_tz_fmt::custom_time_format(fmt).as_str()) - .parse_to_owned() - } - } - .unwrap(); - let recent = match style { - TimeStyle::Iso => Some(StrftimeItems::new("%m-%d %H:%M")), - // See comment above about locale - TimeStyle::Locale => Some(StrftimeItems::new("%b %e %H:%M")), - _ => None, - } - .map(|x| x.collect()); - let recent_time_threshold = if recent.is_some() { - // According to GNU a Gregorian year has 365.2425 * 24 * 60 * 60 == 31556952 seconds on the average. - Some(Local::now() - TimeDelta::try_seconds(31_556_952 / 2).unwrap()) - } else { - None - }; - - TimeStyler { - default, - recent, - recent_time_threshold, - } - } - - /// Format a DateTime, using `recent` format if available, and the DateTime - /// is recent enough. +impl TimeStyle { + /// Format the given time according to this time format style. fn format(&self, time: DateTime) -> String { - if self.recent.is_none() || time <= self.recent_time_threshold.unwrap() { - time.format_with_items(self.default.iter()) - } else { - time.format_with_items(self.recent.as_ref().unwrap().iter()) + let recent = is_recent(time); + match (self, recent) { + (Self::FullIso, _) => time.format("%Y-%m-%d %H:%M:%S.%f %z").to_string(), + (Self::LongIso, _) => time.format("%Y-%m-%d %H:%M").to_string(), + (Self::Iso, true) => time.format("%m-%d %H:%M").to_string(), + (Self::Iso, false) => time.format("%Y-%m-%d ").to_string(), + // spell-checker:ignore (word) datetime + //In this version of chrono translating can be done + //The function is chrono::datetime::DateTime::format_localized + //However it's currently still hard to get the current pure-rust-locale + //So it's not yet implemented + (Self::Locale, true) => time.format("%b %e %H:%M").to_string(), + (Self::Locale, false) => time.format("%b %e %Y").to_string(), + (Self::Format(fmt), _) => time + .format(custom_tz_fmt::custom_time_format(fmt).as_str()) + .to_string(), } - .to_string() } } @@ -2093,8 +2060,6 @@ struct ListState<'a> { uid_cache: HashMap, #[cfg(unix)] gid_cache: HashMap, - - time_styler: TimeStyler, } #[allow(clippy::cognitive_complexity)] @@ -2111,7 +2076,6 @@ pub fn list(locs: Vec<&Path>, config: &Config) -> UResult<()> { uid_cache: HashMap::new(), #[cfg(unix)] gid_cache: HashMap::new(), - time_styler: TimeStyler::new(&config.time_style), }; for loc in locs { @@ -2907,7 +2871,7 @@ fn display_item_long( }; output_display.extend(b" "); - output_display.extend(display_date(md, config, state).as_bytes()); + output_display.extend(display_date(md, config).as_bytes()); output_display.extend(b" "); let item_name = display_item_name( @@ -3111,9 +3075,9 @@ fn get_time(md: &Metadata, config: &Config) -> Option> { Some(time.into()) } -fn display_date(metadata: &Metadata, config: &Config, state: &mut ListState) -> String { +fn display_date(metadata: &Metadata, config: &Config) -> String { match get_time(metadata, config) { - Some(time) => state.time_styler.format(time), + Some(time) => config.time_style.format(time), None => "???".into(), } }