Implement some more delta steps
This commit is contained in:
parent
9920b00916
commit
d105d959fa
4 changed files with 99 additions and 35 deletions
|
|
@ -12,6 +12,7 @@ mod delta;
|
||||||
mod entry;
|
mod entry;
|
||||||
mod error;
|
mod error;
|
||||||
mod range;
|
mod range;
|
||||||
|
mod util;
|
||||||
|
|
||||||
impl Files {
|
impl Files {
|
||||||
pub fn eval(&self, mode: EntryMode, range: DateRange) -> Result<Vec<Entry>> {
|
pub fn eval(&self, mode: EntryMode, range: DateRange) -> Result<Vec<Entry>> {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use chrono::{Datelike, Duration, NaiveDate};
|
||||||
|
|
||||||
use crate::files::commands::{self, Span, Spanned, Time, Weekday};
|
use crate::files::commands::{self, Span, Spanned, Time, Weekday};
|
||||||
|
|
||||||
use super::{Error, Result};
|
use super::{util, Error, Result};
|
||||||
|
|
||||||
/// Like [`commands::DeltaStep`] but includes a new constructor,
|
/// Like [`commands::DeltaStep`] but includes a new constructor,
|
||||||
/// [`DeltaStep::Time`].
|
/// [`DeltaStep::Time`].
|
||||||
|
|
@ -178,21 +178,22 @@ impl DeltaEval {
|
||||||
|
|
||||||
fn apply(&mut self, step: &Spanned<DeltaStep>) -> Result<()> {
|
fn apply(&mut self, step: &Spanned<DeltaStep>) -> Result<()> {
|
||||||
match step.value {
|
match step.value {
|
||||||
DeltaStep::Year(n) => self.step_year(step.span, n),
|
DeltaStep::Year(n) => self.step_year(step.span, n)?,
|
||||||
DeltaStep::Month(n) => self.step_month(step.span, n),
|
DeltaStep::Month(n) => self.step_month(step.span, n)?,
|
||||||
DeltaStep::MonthReverse(n) => self.step_month_reverse(step.span, n),
|
DeltaStep::MonthReverse(n) => self.step_month_reverse(step.span, n)?,
|
||||||
DeltaStep::Day(n) => self.step_day(step.span, n),
|
DeltaStep::Day(n) => self.step_day(n),
|
||||||
DeltaStep::Week(n) => self.step_week(step.span, n),
|
DeltaStep::Week(n) => self.step_week(n),
|
||||||
DeltaStep::Hour(n) => self.step_hour(step.span, n),
|
DeltaStep::Hour(n) => self.step_hour(step.span, n)?,
|
||||||
DeltaStep::Minute(n) => self.step_minute(step.span, n),
|
DeltaStep::Minute(n) => self.step_minute(step.span, n)?,
|
||||||
DeltaStep::Weekday(n, wd) => self.step_weekday(step.span, n, wd),
|
DeltaStep::Weekday(n, wd) => self.step_weekday(n, wd),
|
||||||
DeltaStep::Time(time) => self.step_time(step.span, time),
|
DeltaStep::Time(time) => self.step_time(step.span, time)?,
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_year(&mut self, span: Span, amount: i32) -> Result<()> {
|
fn step_year(&mut self, span: Span, amount: i32) -> Result<()> {
|
||||||
let curr = self.curr;
|
let year = self.curr.year() + amount;
|
||||||
match NaiveDate::from_ymd_opt(curr.year() + amount, curr.month(), curr.day()) {
|
match NaiveDate::from_ymd_opt(year, self.curr.month(), self.curr.day()) {
|
||||||
None => Err(self.err_step(span)),
|
None => Err(self.err_step(span)),
|
||||||
Some(next) => {
|
Some(next) => {
|
||||||
self.curr = next;
|
self.curr = next;
|
||||||
|
|
@ -202,10 +203,8 @@ impl DeltaEval {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_month(&mut self, span: Span, amount: i32) -> Result<()> {
|
fn step_month(&mut self, span: Span, amount: i32) -> Result<()> {
|
||||||
let month0 = self.curr.month0() as i32 + amount;
|
let (year, month) = util::add_months(self.curr.year(), self.curr.month(), amount);
|
||||||
let year = self.curr.year() + month0.div_euclid(12);
|
match NaiveDate::from_ymd_opt(year, month, self.curr.day()) {
|
||||||
let month0 = month0.rem_euclid(12) as u32;
|
|
||||||
match NaiveDate::from_ymd_opt(year, month0 + 1, self.curr.day()) {
|
|
||||||
None => Err(self.err_step(span)),
|
None => Err(self.err_step(span)),
|
||||||
Some(next) => {
|
Some(next) => {
|
||||||
self.curr = next;
|
self.curr = next;
|
||||||
|
|
@ -215,29 +214,27 @@ impl DeltaEval {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_month_reverse(&mut self, span: Span, amount: i32) -> Result<()> {
|
fn step_month_reverse(&mut self, span: Span, amount: i32) -> Result<()> {
|
||||||
todo!()
|
// Offset from the last day of the month
|
||||||
|
let end_offset = self.curr.day() - util::month_length(self.curr.year(), self.curr.month());
|
||||||
|
let (year, month) = util::add_months(self.curr.year(), self.curr.month(), amount);
|
||||||
|
let day = end_offset + util::month_length(year, month);
|
||||||
|
match NaiveDate::from_ymd_opt(year, month, day) {
|
||||||
|
None => Err(self.err_step(span)),
|
||||||
|
Some(next) => {
|
||||||
|
self.curr = next;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_day(&mut self, span: Span, amount: i32) -> Result<()> {
|
fn step_day(&mut self, amount: i32) {
|
||||||
let delta = Duration::days(amount.into());
|
let delta = Duration::days(amount.into());
|
||||||
match self.curr.checked_add_signed(delta) {
|
self.curr += delta;
|
||||||
None => Err(self.err_step(span)),
|
|
||||||
Some(next) => {
|
|
||||||
self.curr = next;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_week(&mut self, span: Span, amount: i32) -> Result<()> {
|
fn step_week(&mut self, amount: i32) {
|
||||||
let delta = Duration::days((7 * amount).into());
|
let delta = Duration::days((7 * amount).into());
|
||||||
match self.curr.checked_add_signed(delta) {
|
self.curr += delta;
|
||||||
None => Err(self.err_step(span)),
|
|
||||||
Some(next) => {
|
|
||||||
self.curr = next;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_hour(&mut self, span: Span, amount: i32) -> Result<()> {
|
fn step_hour(&mut self, span: Span, amount: i32) -> Result<()> {
|
||||||
|
|
@ -248,8 +245,18 @@ impl DeltaEval {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_weekday(&mut self, span: Span, amount: i32, weekday: Weekday) -> Result<()> {
|
fn step_weekday(&mut self, amount: i32, weekday: Weekday) {
|
||||||
todo!()
|
let curr_wd: Weekday = self.curr.weekday().into();
|
||||||
|
#[allow(clippy::comparison_chain)] // The if looks better in this case
|
||||||
|
if amount > 0 {
|
||||||
|
let rest: i32 = curr_wd.until(weekday).into();
|
||||||
|
let days = rest + (amount - 1) * 7;
|
||||||
|
self.curr += Duration::days(days.into());
|
||||||
|
} else if amount < 0 {
|
||||||
|
let rest: i32 = weekday.until(curr_wd).into();
|
||||||
|
let days = rest + (amount - 1) * 7;
|
||||||
|
self.curr -= Duration::days(days.into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step_time(&mut self, span: Span, time: Time) -> Result<()> {
|
fn step_time(&mut self, span: Span, time: Time) -> Result<()> {
|
||||||
|
|
|
||||||
19
src/eval/util.rs
Normal file
19
src/eval/util.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
use chrono::{Datelike, NaiveDate};
|
||||||
|
|
||||||
|
pub fn is_leap_year(year: i32) -> bool {
|
||||||
|
NaiveDate::from_ymd_opt(year, 2, 29).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_months(year: i32, month: u32, delta: i32) -> (i32, u32) {
|
||||||
|
let month0 = (month as i32) - 1 + delta;
|
||||||
|
let year = year + month0.div_euclid(12);
|
||||||
|
let month = month0.rem_euclid(12) as u32 + 1;
|
||||||
|
(year, month)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn month_length(year: i32, month: u32) -> u32 {
|
||||||
|
NaiveDate::from_ymd_opt(year, month + 1, 1)
|
||||||
|
.unwrap_or_else(|| NaiveDate::from_ymd(year + 1, 1, 1))
|
||||||
|
.pred()
|
||||||
|
.day()
|
||||||
|
}
|
||||||
|
|
@ -79,6 +79,20 @@ pub enum Weekday {
|
||||||
Sunday,
|
Sunday,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<chrono::Weekday> for Weekday {
|
||||||
|
fn from(wd: chrono::Weekday) -> Self {
|
||||||
|
match wd {
|
||||||
|
chrono::Weekday::Mon => Self::Monday,
|
||||||
|
chrono::Weekday::Tue => Self::Tuesday,
|
||||||
|
chrono::Weekday::Wed => Self::Wednesday,
|
||||||
|
chrono::Weekday::Thu => Self::Thursday,
|
||||||
|
chrono::Weekday::Fri => Self::Friday,
|
||||||
|
chrono::Weekday::Sat => Self::Saturday,
|
||||||
|
chrono::Weekday::Sun => Self::Sunday,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Weekday {
|
impl Weekday {
|
||||||
pub fn name(&self) -> &'static str {
|
pub fn name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
|
|
@ -91,6 +105,29 @@ impl Weekday {
|
||||||
Weekday::Sunday => "sun",
|
Weekday::Sunday => "sun",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn num(&self) -> u8 {
|
||||||
|
match self {
|
||||||
|
Weekday::Monday => 1,
|
||||||
|
Weekday::Tuesday => 2,
|
||||||
|
Weekday::Wednesday => 3,
|
||||||
|
Weekday::Thursday => 4,
|
||||||
|
Weekday::Friday => 5,
|
||||||
|
Weekday::Saturday => 6,
|
||||||
|
Weekday::Sunday => 7,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// How many days from now until the other weekday.
|
||||||
|
pub fn until(&self, other: Weekday) -> u8 {
|
||||||
|
let num_self = self.num();
|
||||||
|
let num_other = other.num();
|
||||||
|
if num_self <= num_other {
|
||||||
|
num_other - num_self
|
||||||
|
} else {
|
||||||
|
num_other + 7 - num_self
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue