diff --git a/doc/lsd.md b/doc/lsd.md index 78a120465..1a33f5f3a 100644 --- a/doc/lsd.md +++ b/doc/lsd.md @@ -99,7 +99,11 @@ lsd is a ls command with a lot of pretty colours and some other stuff to enrich : When to use terminal colours [default: auto] [possible values: always, auto, never] `--date ...` -: How to display date [possible values: date, locale, relative, +date-time-format] [default: date] +: How to display date [possible values: date, iso, locale, relative, +date-time-format] [default: date] + + The `iso` format displays dates in ISO format (MM-DD HH:MM for recent files, YYYY-MM-DD for older files). + + For custom formats using +date-time-format, you can specify dual-line formats by separating two format strings with a newline (e.g., '+%F\n%H:%M'). The first format is used for old files (>6 months), and the second for recent files. `--depth ...` : Stop recursing into directories after reaching specified depth diff --git a/doc/samples/config-sample.yaml b/doc/samples/config-sample.yaml index 3da640e5d..b922f6511 100644 --- a/doc/samples/config-sample.yaml +++ b/doc/samples/config-sample.yaml @@ -35,8 +35,9 @@ color: # This specifies the date format for the date column. The freeform format # accepts a strftime like string. # When "classic" is set, this is set to "date". -# Possible values: date, locale, relative, '+' +# Possible values: date, iso, locale, relative, '+' # `date_format` will be a `strftime` formatted value. e.g. `date: '+%d %b %y %X'` will give you a date like this: 17 Jun 21 20:14:55 +# For dual-line date formats (recent vs old files), use a newline to separate formats. e.g. `date: '+%F\n%H:%M'` uses '%F' for old files and '%H:%M' for recent files. date: date # == Dereference == diff --git a/src/app.rs b/src/app.rs index c8d80c7cb..e11c20a57 100644 --- a/src/app.rs +++ b/src/app.rs @@ -84,7 +84,7 @@ pub struct Cli { #[arg(long)] pub total_size: bool, - /// How to display date [default: date] [possible values: date, locale, relative, +date-time-format] + /// How to display date [default: date] [possible values: date, iso, locale, relative, +date-time-format] #[arg(long, value_parser = validate_date_argument)] pub date: Option, @@ -205,10 +205,10 @@ pub struct Cli { fn validate_date_argument(arg: &str) -> Result { if arg.starts_with('+') { validate_time_format(arg) - } else if arg == "date" || arg == "relative" || arg == "locale" { + } else if arg == "date" || arg == "relative" || arg == "locale" || arg == "iso" { Result::Ok(arg.to_owned()) } else { - Result::Err("possible values: date, locale, relative, +date-time-format".to_owned()) + Result::Err("possible values: date, iso, locale, relative, +date-time-format".to_owned()) } } diff --git a/src/flags/date.rs b/src/flags/date.rs index a316cafe9..b15b701e8 100644 --- a/src/flags/date.rs +++ b/src/flags/date.rs @@ -36,6 +36,7 @@ impl DateFlag { "date" => Some(Self::Date), "locale" => Some(Self::Locale), "relative" => Some(Self::Relative), + "iso" => Some(Self::Iso), _ if value.starts_with('+') => Self::from_format_string(value), _ => { print_error!("Not a valid date value: {}.", value); @@ -131,6 +132,13 @@ mod test { assert_eq!(Some(DateFlag::Relative), DateFlag::from_cli(&cli)); } + #[test] + fn test_from_cli_iso() { + let argv = ["lsd", "--date", "iso"]; + let cli = Cli::try_parse_from(argv).unwrap(); + assert_eq!(Some(DateFlag::Iso), DateFlag::from_cli(&cli)); + } + #[test] fn test_from_cli_format() { let argv = ["lsd", "--date", "+%F"]; diff --git a/src/meta/date.rs b/src/meta/date.rs index 007023c35..2c7b2d944 100644 --- a/src/meta/date.rs +++ b/src/meta/date.rs @@ -61,7 +61,17 @@ impl Date { val.format("%F").to_string() } } - DateFlag::Formatted(format) => val.format_localized(format, locale).to_string(), + DateFlag::Formatted(format) => { + let vec: Vec<&str> = format.split('\n').collect(); + + if vec.len() == 1 { + val.format_localized(format, locale).to_string() + } else if *val > Local::now() - Duration::seconds(15_778_476) { + val.format_localized(vec[1], locale).to_string() + } else { + val.format_localized(vec[0], locale).to_string() + } + } } } else { String::from('-') @@ -347,6 +357,67 @@ mod test { fs::remove_file(file_path).unwrap(); } + #[test] + fn test_recent_format_now() { + let mut file_path = env::temp_dir(); + file_path.push("test_recent_format_now.tmp"); + + let creation_date = Local::now(); + let success = cross_platform_touch(&file_path, &creation_date) + .unwrap() + .success(); + assert!(success, "failed to exec touch"); + + let colors = Colors::new(ThemeOption::Default); + let date = Date::from(&file_path.metadata().unwrap()); + + let flags = Flags { + date: DateFlag::Formatted(String::from("%F\n%H:%M")), + ..Default::default() + }; + + assert_eq!( + creation_date + .format("%H:%M") + .to_string() + .with(Color::AnsiValue(40)), + date.render(&colors, &flags) + ); + + fs::remove_file(file_path).unwrap(); + } + + #[test] + fn test_recent_format_year_old() { + let mut file_path = env::temp_dir(); + file_path.push("test_recent_format_year_old.tmp"); + + #[allow(deprecated)] + let creation_date = Local::now() - Duration::days(400); + let success = cross_platform_touch(&file_path, &creation_date) + .unwrap() + .success(); + assert!(success, "failed to exec touch"); + + let colors = Colors::new(ThemeOption::Default); + let date = Date::from(&file_path.metadata().unwrap()); + + let flags = Flags { + date: DateFlag::Formatted(String::from("%F\n%H:%M")), + ..Default::default() + }; + + assert_eq!( + creation_date + .format("%F") + .to_string() + .with(Color::AnsiValue(36)), + date.render(&colors, &flags) + ); + + fs::remove_file(file_path).unwrap(); + } + #[test] #[cfg(all(not(windows), target_arch = "x86_64"))] fn test_bad_date() {