hutools/date/between/
between_months.rs1use 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}