hutools/date/between/
between_months.rs

1use chrono::{Date, Datelike, TimeZone};
2
3#[cfg(test)]
4mod test {
5    use super::*;
6    use chrono::Utc;
7
8    #[test]
9    fn test_between_months() {
10        let start = Utc.ymd(2008, 8, 8);
11        let end = Utc.ymd(2018, 9, 9);
12        let date_range = (start, end);
13        let result = between_months(date_range);
14        let actual = 121;
15        assert_eq!(result, Some(actual));
16    }
17
18    #[test]
19    fn test_between_month_1() {
20        let start = Utc.ymd(2008, 8, 8);
21        let end = Utc.ymd(2018, 9, 1);
22        let data_range = (start, end);
23        let result = between_months(data_range);
24        let actual = 120;
25        assert_eq!(result, Some(actual));
26    }
27    #[test]
28    fn test_between_months_2() {
29        let start = Utc.ymd(2008, 8, 8);
30        let end = Utc.ymd(2018, 8, 16);
31        let date_range = (start, end);
32        let result = between_months(date_range);
33        let actual = 120;
34        assert_eq!(result, Some(actual));
35    }
36    #[test]
37    fn test_between_months_3() {
38        let start = Utc.ymd(2008, 8, 8);
39        let end = Utc.ymd(2018, 8, 2);
40        let date_range = (start, end);
41        let result = between_months(date_range);
42        let actual = 119;
43        assert_eq!(result, Some(actual));
44    }
45}
46
47pub fn between_months<Tz>(date_range: (Date<Tz>, Date<Tz>)) -> Option<i64>
48where
49    Tz: TimeZone,
50{
51    let (start, end) = date_range;
52    let start_year = start.year();
53    let end_year = end.year();
54    let start_month = start.month() as i32;
55    let end_month = end.month() as i32;
56    let start_day = start.day();
57    let end_day = end.day();
58    let diff_day = end_day.checked_sub(start_day);
59    let diff = if diff_day.is_some() { 0 } else { -1 };
60    let diff_month = end_month
61        .checked_sub(start_month)
62        .and_then(|x| x.checked_add(diff));
63    let diff_year = end_year.checked_sub(start_year);
64    diff_year
65        .and_then(|x| x.checked_mul(12))
66        .and_then(|x| diff_month.and_then(|y| (y as i64).checked_add(x as i64)))
67}