Processing dates and times with Rust and chrono

Yesterday, we looked at a few date calculations in Perl. Here are the same calculations in Rust using the chrono crate.

use chrono::{Datelike, Duration, TimeZone};

fn main() {
    let now = chrono::Local::now();

    // Finding the date in 10 days time
    println!("{}", now + Duration::days(10));

    // Finding the date of the previous Saturday
    let days = 1 + now.date().weekday().num_days_from_sunday();
    println!("{}", now - Duration::days(days as i64));

    // Finding the date of the first Monday in a given year
    let first_doy = chrono::Local.ymd(now.year(), 1, 1).and_hms(0, 0, 0);
    let days = (8 - first_doy.date().weekday().num_days_from_sunday()) % 7;
    println!("{}", first_doy + Duration::days(days as i64));
}

One issue with the original post was that Time::Piece's day_of_week gives 0..6 starting from Sunday, while DateTime's day_of_week gives 1..7 starting from Monday (so that DateTime calcuation is wrong on Sundays: it will back up 8 days instead of 1). Rather than day_of_week, chrono supplies a number of methods to choose from: we used num_days_from_sunday above. As with many things in Rust, we are forced to be explicit.

Note that running this here and now (2021-11-12 08:46:04.487898162 -05:00) gives

❯ cargo run -q
2021-11-22 08:46:04.487898162 -05:00
2021-11-06 09:46:04.487898162 -04:00
2021-01-04 00:00:00 -05:00

We moved the clocks back from Daylight Saving Time to Standard Time on Sunday, so last Saturday was a different offset!

One of the nice suprises with Rust is that, despite its being a "low-level" programming language (like C), it has some nice affordances for "higher-level" programming (like Perl).