Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datelike should have methods to add/sub a number of calendar day/month/year #290

Closed
vincentdephily opened this issue Nov 14, 2018 · 3 comments

Comments

@vincentdephily
Copy link

Datelike currently offers a set of with_*() methods to set the day/month/year, but the resulting date must be valid (for example calling with_month(13) doesn't translate to january of the next year). You can also add a Duration to a Datelike, but there's no good Duration value for year/month/day because of leap years, various month lengths, and DST.

I'd like to have methods add_days/month/years(i32) -> Self to easily add/subtract the corresponding number of time units. Might want to have add_hour/min/sec/etc() for consistency's sake, although adding a Duration works well in this case (unless we want to handle DST ?).

My usecase is deceptively simple: I write a report and want to know when the next day/week/month/year starts, after a given timestamp. For example I have 2018-11-14T12:34:56z as input and want 2018-12-14T00:00:00z as output (beginning of next month).

This is ugly but doable for "next year":

fn next_year<T>(d: T) -> T where T: Datelike {
  d.with_year(d.year()+1)
    .unwrap()
   .with_month(1)
   .unwrap()
   .with_day(1)
   .unwrap()
   .with_hour(0)
   .unwrap()
   .with_minute(0)
   .unwrap()
   .with_second(0)
   .unwrap()
   // Thankfully I know that my input had a second granularity so I don't care about nanoseconds.
}

But the implementation for next_month/week/day() is not going to be fun.

Incidentally, it with also be nice to have a with_year/month/day/etc() that panics instead of returning a result, for cases like this where the input is hardcoded and known to be correct. Or a with_ymd() and with_hmsn() ;)

@felipenoris
Copy link

I have a similar issue. I just want to get the next/last day out of a Datelike date. For now I'm doing this:

fn next_date<T: Datelike + Copy>(date: T, fwd: bool) -> T {
    let inc: i32 = {
        if fwd {
            1
        } else {
            -1
        }
    };

    match date.with_ordinal((date.ordinal() as i32 + inc) as u32) {
        Some(dt) => dt,
        None =>  {
            if fwd {
                date
                    .with_year(date.year() + 1).unwrap()
                    .with_ordinal(1).unwrap()
            } else {
                date
                    .with_year(date.year() - 1).unwrap()
                    .with_month(12).unwrap()
                    .with_day(31).unwrap()
            }
        }
    }
}

@nyovaya
Copy link

nyovaya commented Dec 20, 2018

I would like to substract NaiveDate from DateTime.

@pitdicker
Copy link
Collaborator

Fixed with #784 and #731.

@djc djc closed this as completed Jun 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants