diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/mod.rs | 66 | ||||
-rw-r--r-- | src/main.rs | 13 | ||||
-rw-r--r-- | src/model/event.rs | 9 |
3 files changed, 77 insertions, 11 deletions
diff --git a/src/cli/mod.rs b/src/cli/mod.rs index b952a75..e7439b5 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,21 +1,71 @@ use anyhow::Result; -use chrono::Local; +use chrono::{Local, NaiveDate, NaiveDateTime, TimeZone}; use rusqlite::Connection; use crate::{db, model::event}; +use crate::model::event::Event; pub fn today(conn: &Connection) -> Result<String> { let today = Local::now().date_naive(); - let mut events = db::events::list_non_recurring_between(conn, today, today)?; + let events = between_inclusive(conn, today, today)?; + Ok(format_events(events)) +} + +pub fn parse_timestamp_range(s: String) -> Option<(NaiveDateTime, NaiveDateTime)> { + match s.split("..").collect::<Vec<&str>>()[..] { + [from, to] => { + let from = from.parse().ok()?; + let to = to.parse().ok()?; + + let from = Local.timestamp_opt(from, 0).single()?; + let to = Local.timestamp_opt(to, 0).single()?; + + Some((from.naive_local(), to.naive_local())) + } + _ => None, + } +} + +pub fn start_between(conn: &Connection, from: NaiveDateTime, to: NaiveDateTime) -> Result<String> { + let from_date = from.date(); + let to_date = to.date(); + let events = between_inclusive(conn, from_date, to_date)?; + println!("{events:?}"); + let events: Vec<Event> = events + .iter() + .filter(|e| { + match e.start { + None => false, + Some(t) => { + let dt = NaiveDateTime::new(e.date, t); + dt >= from && dt < to + } + } + }) + .map(|e| e.clone()) + .collect::<Vec<Event>>(); + Ok(format_events(events)) +} + +fn between_inclusive(conn: &Connection, from: NaiveDate, to: NaiveDate) -> Result<Vec<Event>> { + let mut events = db::events::list_non_recurring_between(conn, from, to)?; let recurring_events = db::events::list_recurring(conn)?; - let repetitions = event::repetitions_between(&recurring_events, today, today); - for repetition in repetitions.values().flatten() { - events.push(repetition.clone()); + let repetitions = event::repetitions_between(&recurring_events, from, to); + for (date, original_events) in repetitions.iter() { + for original_event in original_events { + let event = Event { date: *date, ..original_event.clone() }; + events.push(event); + } } - events.sort_by_key(|e| e.start); - Ok(events + Ok(events) +} + +fn format_events(events: Vec<Event>) -> String { + let mut events = events; + events.sort_by_key(|e| e.local_timestamp()); + events .iter() .map(|e| format!("{}\n", e.pprint())) .collect::<Vec<String>>() - .join("")) + .join("") } diff --git a/src/main.rs b/src/main.rs index d3080ab..4e2a5f2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,18 +17,27 @@ struct Opt { /// List today’s events as plain text #[clap(long = "list-today")] list_today: bool, + + /// Start between <timestamp..timestamp> events as plain text + #[clap(long = "start-between")] + start_between: Option<String>, } fn main() -> Result<()> { let Opt { db_path, list_today, + start_between } = Opt::parse(); let conn = db::init(&db_path)?; if list_today { print!("{}", cli::today(&conn)?); } else { - gui::run(conn); - } + match start_between.and_then(cli::parse_timestamp_range) { + Some((from, to)) => print!("{}", cli::start_between(&conn, from, to)?), + None => gui::run(conn) + } + }; Ok(()) } + diff --git a/src/model/event.rs b/src/model/event.rs index 6cc16a2..dc052fe 100644 --- a/src/model/event.rs +++ b/src/model/event.rs @@ -1,4 +1,4 @@ -use chrono::{NaiveDate, NaiveTime}; +use chrono::{NaiveDate, NaiveTime, NaiveDateTime, Local, TimeZone}; use std::collections::HashMap; use uuid::Uuid; @@ -33,6 +33,13 @@ impl Event { }; format!("{}{}{}{}", start, end, space, self.name) } + + pub fn local_timestamp(&self) -> Option<i64> { + let time = self.start.unwrap_or(NaiveTime::from_hms_opt(0, 0, 0)?); + let naive_datetime = NaiveDateTime::new(self.date, time); + let local_datetime = Local.from_local_datetime(&naive_datetime).single()?; + Some(local_datetime.timestamp()) + } } /// Recurring events in an date range (inclusive) |