1crate::ix!();
2
3pub fn intersect_date_ranges(
4 dates_a: &[NaiveDate],
5 dates_b: &[NaiveDate],
6) -> Vec<NaiveDate> {
7 let set_a: HashSet<_> = dates_a.iter().cloned().collect();
8 let set_b: HashSet<_> = dates_b.iter().cloned().collect();
9 let mut intersection: Vec<NaiveDate> = set_a.intersection(&set_b).cloned().collect();
10 intersection.sort(); intersection
12}
13
14#[cfg(test)]
15mod intersect_date_ranges_tests {
16 use super::*;
17 use chrono::NaiveDate;
18 use std::collections::HashSet;
19
20 #[test]
21 fn test_empty_inputs() {
22 let dates_a: Vec<NaiveDate> = vec![];
23 let dates_b: Vec<NaiveDate> = vec![];
24 let result = intersect_date_ranges(&dates_a, &dates_b);
25 assert!(result.is_empty(), "Intersection of empty inputs should be empty.");
26 }
27
28 #[test]
29 fn test_non_overlapping_date_ranges() {
30 let dates_a = vec![
31 NaiveDate::from_ymd_opt(2024, 1, 1).unwrap(),
32 NaiveDate::from_ymd_opt(2024, 1, 2).unwrap(),
33 ];
34 let dates_b = vec![
35 NaiveDate::from_ymd_opt(2024, 1, 3).unwrap(),
36 NaiveDate::from_ymd_opt(2024, 1, 4).unwrap(),
37 ];
38 let result = intersect_date_ranges(&dates_a, &dates_b);
39 assert!(result.is_empty(), "Non-overlapping ranges should yield an empty intersection.");
40 }
41
42 #[test]
43 fn test_identical_date_ranges() {
44 let dates_a = vec![
45 NaiveDate::from_ymd_opt(2024, 1, 1).unwrap(),
46 NaiveDate::from_ymd_opt(2024, 1, 2).unwrap(),
47 NaiveDate::from_ymd_opt(2024, 1, 3).unwrap(),
48 ];
49 let dates_b = dates_a.clone();
50 let result = intersect_date_ranges(&dates_a, &dates_b);
51 assert_eq!(result.len(), dates_a.len(), "Intersection of identical ranges should match their length.");
52 assert_eq!(result, dates_a, "Intersection of identical ranges should yield the same dates.");
53 }
54
55 #[test]
56 fn test_partially_overlapping_date_ranges() {
57 let dates_a = vec![
58 NaiveDate::from_ymd_opt(2024, 1, 1).unwrap(),
59 NaiveDate::from_ymd_opt(2024, 1, 2).unwrap(),
60 NaiveDate::from_ymd_opt(2024, 1, 3).unwrap(),
61 ];
62 let dates_b = vec![
63 NaiveDate::from_ymd_opt(2024, 1, 2).unwrap(),
64 NaiveDate::from_ymd_opt(2024, 1, 3).unwrap(),
65 NaiveDate::from_ymd_opt(2024, 1, 4).unwrap(),
66 ];
67 let result = intersect_date_ranges(&dates_a, &dates_b);
68 let expected = vec![
69 NaiveDate::from_ymd_opt(2024, 1, 2).unwrap(),
70 NaiveDate::from_ymd_opt(2024, 1, 3).unwrap(),
71 ];
72 assert_eq!(result, expected, "Intersection should yield only overlapping dates.");
73 }
74
75 #[test]
76 fn test_subset_date_ranges() {
77 let dates_a = vec![
78 NaiveDate::from_ymd_opt(2024, 1, 1).unwrap(),
79 NaiveDate::from_ymd_opt(2024, 1, 2).unwrap(),
80 NaiveDate::from_ymd_opt(2024, 1, 3).unwrap(),
81 ];
82 let dates_b = vec![
83 NaiveDate::from_ymd_opt(2024, 1, 2).unwrap(),
84 NaiveDate::from_ymd_opt(2024, 1, 3).unwrap(),
85 ];
86 let result = intersect_date_ranges(&dates_a, &dates_b);
87 assert_eq!(result, dates_b, "Intersection should match the smaller range if it's a subset.");
88 }
89
90 #[test]
91 fn test_disjoint_ranges_with_duplicates() {
92 let dates_a = vec![
93 NaiveDate::from_ymd_opt(2024, 1, 1).unwrap(),
94 NaiveDate::from_ymd_opt(2024, 1, 1).unwrap(), NaiveDate::from_ymd_opt(2024, 1, 2).unwrap(),
96 ];
97 let dates_b = vec![
98 NaiveDate::from_ymd_opt(2024, 1, 2).unwrap(),
99 NaiveDate::from_ymd_opt(2024, 1, 3).unwrap(),
100 NaiveDate::from_ymd_opt(2024, 1, 3).unwrap(), ];
102 let result = intersect_date_ranges(&dates_a, &dates_b);
103 let expected = vec![NaiveDate::from_ymd_opt(2024, 1, 2).unwrap()];
104 assert_eq!(result, expected, "Intersection should ignore duplicates and yield correct results.");
105 }
106}