specifiing dates

This commit is contained in:
Andrei Stoica 2024-04-19 20:19:31 -04:00
parent 4e26695532
commit 5cd03b713c
3 changed files with 90 additions and 5 deletions

View File

@ -25,16 +25,15 @@ digital, automated version of that.
```bash ```bash
git clone https://github.com/andrei-stoica/rusty-tasks.git git clone https://github.com/andrei-stoica/rusty-tasks.git
cd rusty-task cd rusty-task cargo install --path .
cargo install --path .
``` ```
Alternatively, there is a binary download for AMD64 Linux machines available Alternatively, there is a binary download for AMD64 Linux machines available
on the [releases page](https://github.com/andrei-stoica/rusty-tasks/releases). on the [releases page](https://github.com/andrei-stoica/rusty-tasks/releases).
Just drop that anywhere on you PATH. I recommend adding `~/bin` to your PATH Just drop that anywhere on your PATH. I recommend adding `~/bin` to your PATH
and dropping the executable there. and dropping the executable there.
If you are not on a AMD64 Linux machine, you will need to build from source. If you are not on an AMD64 Linux machine, you will need to build from source.
I have not tested this on other platforms, so I hesitate to provide binaries I have not tested this on other platforms, so I hesitate to provide binaries
for them. for them.
@ -46,6 +45,7 @@ Usage: rusty-tasks [OPTIONS]
Options: Options:
-c, --config <FILE> set config file to use -c, --config <FILE> set config file to use
-C, --current-config show current config file -C, --current-config show current config file
-d, --date <DATE> view a specific date's file (format: YYYY-MM-DD)
-p, --previous <PREVIOUS> view previous day's notes [default: 0] -p, --previous <PREVIOUS> view previous day's notes [default: 0]
-l, --list list closest files to date -l, --list list closest files to date
-n, --number <NUMBER> number of files to list [default: 5] -n, --number <NUMBER> number of files to list [default: 5]
@ -61,6 +61,12 @@ Use `rust-task -p <n>` to access a previous day's file where `<n>` is the number
of days back you want to go. If a file does not exist for that day, it will of days back you want to go. If a file does not exist for that day, it will
default to the closest to that date. A value of 0 represents today's file. default to the closest to that date. A value of 0 represents today's file.
Alternatively, use `--date` or `-d` to specify a date specifically. Preferably
in the format year-month-day, padding with zero is optional. However, if the
year, or, year and month are omitted they will be filled in with the current
date's year and month. For example, If the current date is `2024-2-30`, the
string `4` will resolve to `2024-2-4`, and `1-4` will resolve to `2024-1-4`.
Specify a custom config location with `-c`, otherwise, it will scan for a config Specify a custom config location with `-c`, otherwise, it will scan for a config
in the locations specified in the [config section](#config). If no config in the locations specified in the [config section](#config). If no config
exists it will create one. To see what config is being loaded you can use `-C`. exists it will create one. To see what config is being loaded you can use `-C`.

View File

@ -1,3 +1,4 @@
use chrono::{Datelike, NaiveDate};
use clap::Parser; use clap::Parser;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -10,6 +11,9 @@ pub struct Args {
#[arg(short = 'C', long)] #[arg(short = 'C', long)]
pub current_config: bool, pub current_config: bool,
/// view a specific date's file (YYYY-MM-DD)
#[arg(short, long)]
pub date: Option<String>,
/// view previous day's notes /// view previous day's notes
#[arg(short = 'p', long, default_value_t = 0)] #[arg(short = 'p', long, default_value_t = 0)]
pub previous: u16, pub previous: u16,
@ -27,3 +31,74 @@ pub struct Args {
#[arg(short, long, action = clap::ArgAction::Count)] #[arg(short, long, action = clap::ArgAction::Count)]
pub verbose: u8, pub verbose: u8,
} }
pub fn smart_parse_date(date_str: &str, cur_date: &NaiveDate) -> Option<NaiveDate> {
let full_date_fmt = "%Y-%m-%d";
if let Ok(date) = NaiveDate::parse_from_str(date_str, &full_date_fmt) {
return Some(date);
}
let parts: Vec<&str> = date_str.split('-').collect();
match parts.len() {
1 => cur_date.with_day(parts[0].parse().unwrap_or(cur_date.day())),
2 => cur_date
.with_day(parts[1].parse().unwrap_or(cur_date.day()))?
.with_month(parts[0].parse().unwrap_or(cur_date.month())),
3 => NaiveDate::from_ymd_opt(
parts[0].parse().ok()?,
parts[1].parse().ok()?,
parts[2].parse().ok()?,
),
_ => None,
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_smart_parse_date() {
let good_date = NaiveDate::from_ymd_opt(2024, 01, 03).expect("Invalid date specified");
let good_date_str = good_date.format("%Y-%m-%d").to_string();
assert_eq!(
Some(good_date),
smart_parse_date(&good_date_str, &good_date)
);
let no_padding_date_str = "2024-1-3";
assert_eq!(
Some(good_date),
smart_parse_date(no_padding_date_str, &good_date)
);
let bad_day_str = "2024-01-99";
assert_eq!(None, smart_parse_date(bad_day_str, &good_date));
let no_day_str = "2024-01";
assert_eq!(None, smart_parse_date(no_day_str, &good_date));
let bad_month_str = "2024-25-01";
assert_eq!(None, smart_parse_date(bad_month_str, &good_date));
let no_month_str = "2024-14";
assert_eq!(None, smart_parse_date(no_month_str, &good_date));
let no_year_str = "01-03";
assert_eq!(Some(good_date), smart_parse_date(no_year_str, &good_date));
let bad_month_no_year_str = "25-01";
assert_eq!(None, smart_parse_date(bad_month_no_year_str, &good_date));
let bad_day_no_year_str = "01-35";
assert_eq!(None, smart_parse_date(bad_day_no_year_str, &good_date));
let no_year_month_str = "03";
assert_eq!(
Some(good_date),
smart_parse_date(no_year_month_str, &good_date)
);
let bad_day_no_year_month_str = "35";
assert_eq!(
None,
smart_parse_date(bad_day_no_year_month_str, &good_date)
);
}
}

View File

@ -97,7 +97,11 @@ fn main() {
// get clossest files to specified date // get clossest files to specified date
let today = Local::now().date_naive(); let today = Local::now().date_naive();
let target = today - TimeDelta::try_days(args.previous.into()).unwrap(); let target = if let Some(date_str) = args.date {
cli::smart_parse_date(&date_str, &today).expect("Could not parse date")
} else {
today - TimeDelta::try_days(args.previous.into()).unwrap()
};
let closest_files = TodoFile::get_closest_files(files.collect(), target, args.number); let closest_files = TodoFile::get_closest_files(files.collect(), target, args.number);
// list files // list files
if args.list { if args.list {