Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion doc/lsd.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <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 <num>...`
: Stop recursing into directories after reaching specified depth
Expand Down
3 changes: 2 additions & 1 deletion doc/samples/config-sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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, '+<date_format>'
# Possible values: date, iso, locale, relative, '+<date_format>'
# `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 ==
Expand Down
6 changes: 3 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,

Expand Down Expand Up @@ -205,10 +205,10 @@ pub struct Cli {
fn validate_date_argument(arg: &str) -> Result<String, String> {
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())
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/flags/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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"];
Expand Down
73 changes: 72 additions & 1 deletion src/meta/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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('-')
Expand Down Expand Up @@ -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() {
Expand Down