Skip to content

RelativeDuration::num_days() misleading output (or name?) #32

@bobhy

Description

@bobhy

It seems that num_days(), num_weeks() and num_months() simply fetch the internal implementation fields unchanged.
I was expecting these would return the total length of the duration (truncated to whole days, weeks, months).
I wasn't expecting num_months() to be infallible, since it should need a reference Date to base calculations on in the general case.

Here's a sample program:

#![allow(unused_imports, dead_code)]
extern crate calends;
extern crate chrono;
use calends::RelativeDuration;
use chrono::{DateTime, Datelike, NaiveDate, NaiveDateTime, TimeZone, Timelike, Utc};
use std::fmt::Display;
pub fn main() {

    // simple case, length of month doesn't affect outcome:
    let rd1 = RelativeDuration::from_mwd(0, 3, 12);
    assert_contrapositive(rd1.num_weeks(), 3 + (12 / 7), "from_mwd().num_weeks");
    assert_contrapositive(rd1.num_days(), (3 * 7) + 12, "from_mwd().num_days");

    //  trickier case, length of month *does* come into it.

    let rd2 = RelativeDuration::from_duration_between(
        NaiveDate::from_ymd_opt(2023, 3, 31).unwrap(),
        NaiveDate::from_ymd_opt(2023, 4, 1).unwrap(),
    );

    assert_contrapositive(rd2.num_months(), 1, "from_duration_between().num_months");
    assert_contrapositive(rd2.num_days(), 1, "from_duration_between().num_days");
}

fn assert_contrapositive<T: Display + PartialOrd>(observed: T, expected: T, tag: &str) {
    if observed == expected {
        println!("SUCCESS?! Case {tag}, observed and expected were both: {observed}");
    } else {
        println!("Mismatch. Case {tag}, observed: {observed}, expected: {expected}");
    }
}

Which prints this, when run:

〉cargo run --quiet --example bug_rd
Mismatch. Case from_mwd().num_weeks, observed: 3, expected: 4
Mismatch. Case from_mwd().num_days, observed: 12, expected: 33
SUCCESS?! Case from_duration_between().num_months, observed and expected were both: 1
Mismatch. Case from_duration_between().num_days, observed: -30, expected: 1

FWIW, I think calends should have a helper function that does accept a date and can return total_days, total_weeks, total_months. (Unless there's already a way to get these? Calendar arithmetic is tricky.)

Plus, it would be OK for RelativeImpl to have the simple getters.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions