How to get the start and the end of date for each month with NaiveDate (Rust)?

Viewed 36

How to get the last date of a month with chrono::NaiveDate. I try to search the manual but can't found anything useful.

   use chrono::{NaiveDate, Datelike};

   // from January to December m = 1 - 12
   for m in 1..=12 {
        let end = ..... ?? 
        let start_date = NaiveDate::from_ymd(year, m, 1);  /// each month starts with 1
        let end_date = NaiveDate::from_ymd(year, m, end); /// here's the problem
        container.push((start_date, end_date));
   }

the closest would be to use Datelike::day https://docs.rs/chrono/0.4.6/chrono/trait.Datelike.html#tymethod.day0 and subtract 1 day from it, but I don't know how to do that with NaiveDate. I'm open to any suggestion. Thanks in advance.

2 Answers

Proposal for requested function

The function last_day_of_month already was proposed to be added to the chrono library on GitHub, but was not accepted.

The Code

The following solution works exactly like @Zeppi's solution, but uses a more rusty approach. An Option<NativeDate> returned from NativeDate::from_ymd_opt is used to check whether the month is the 12. month to the switch to the edge-case, where the day is the last day of the month.

fn last_day_of_month(year: i32, month: u32) -> NaiveDate {
    NaiveDate::from_ymd_opt(year, month + 1, 1)
        .unwrap_or(NaiveDate::from_ymd(year + 1, 1, 1))
        .pred()
}

Credits to @lifthrasiir on GitHub for the code

Sources

Chrono library Issue 69: Provide days_in_month()

Chrono library Issue 29: Leap year and last day of month

You can use pred()or pre_opt().

A very dirty solution that works like this

for m in 1..=12 {
        let start_date = NaiveDate::from_ymd(2022, m, 1);
        
        let mut end_date;
        if m < 12 {
            end_date = NaiveDate::from_ymd(2022, m + 1, 1).pred();    
        } else {
            end_date = NaiveDate::from_ymd(2023, 1, 1).pred();    
        }

        println!("{:?}", end_date);
   }
Related