transit_model/
validity_period.rs

1// Copyright (C) 2017 Hove and/or its affiliates.
2//
3// This program is free software: you can redistribute it and/or modify it
4// under the terms of the GNU Affero General Public License as published by the
5// Free Software Foundation, version 3.
6
7// This program is distributed in the hope that it will be useful, but WITHOUT
8// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
10// details.
11
12// You should have received a copy of the GNU Affero General Public License
13// along with this program. If not, see <https://www.gnu.org/licenses/>
14
15//! Some utilities to set and/or calculate validity periods.
16use crate::{
17    objects::{Calendar, Dataset, ValidityPeriod},
18    Result,
19};
20use std::collections::BTreeSet;
21use typed_index_collection::CollectionWithId;
22
23fn get_validity_period(calendars: &CollectionWithId<Calendar>) -> Option<ValidityPeriod> {
24    let dates = calendars.values().fold(BTreeSet::new(), |acc, c| {
25        acc.union(&c.dates).cloned().collect()
26    });
27
28    if dates.is_empty() {
29        return None;
30    }
31
32    Some(ValidityPeriod {
33        start_date: *dates.iter().next().unwrap(),
34        end_date: *dates.iter().next_back().unwrap(),
35    })
36}
37
38/// Define the Validity Period of the dataset from all the available services.
39pub fn compute_dataset_validity_period(
40    dataset: &mut Dataset,
41    calendars: &CollectionWithId<Calendar>,
42) -> Result<()> {
43    let validity_period = get_validity_period(calendars);
44
45    if let Some(vp) = validity_period {
46        dataset.start_date = vp.start_date;
47        dataset.end_date = vp.end_date;
48    }
49
50    Ok(())
51}
52
53/// Set the validity period of a dataset.
54///
55/// Take also a look at the `compute_dataset_validity_period` function that
56/// can automatically calculate the validity period from the Services dates.
57pub fn set_dataset_validity_period(
58    dataset: &mut Dataset,
59    service_validity_period: &ValidityPeriod,
60) {
61    dataset.start_date = if service_validity_period.start_date < dataset.start_date {
62        service_validity_period.start_date
63    } else {
64        dataset.start_date
65    };
66    dataset.end_date = if service_validity_period.end_date > dataset.end_date {
67        service_validity_period.end_date
68    } else {
69        dataset.end_date
70    };
71}
72
73#[cfg(test)]
74mod tests {
75
76    mod set_validity_period {
77        use super::super::*;
78        use crate::objects::{Dataset, Date, ValidityPeriod};
79        use chrono::NaiveDate;
80        use pretty_assertions::assert_eq;
81
82        #[test]
83        fn no_existing_validity_period() {
84            let start_date = Date::from_ymd_opt(2019, 1, 1).unwrap();
85            let end_date = Date::from_ymd_opt(2019, 6, 30).unwrap();
86            let mut dataset = Dataset {
87                id: String::from("dataset_id"),
88                contributor_id: String::from("contributor_id"),
89                start_date: NaiveDate::MAX,
90                end_date: NaiveDate::MIN,
91                ..Default::default()
92            };
93            let service_validity_period = ValidityPeriod {
94                start_date,
95                end_date,
96            };
97            set_dataset_validity_period(&mut dataset, &service_validity_period);
98            assert_eq!(start_date, dataset.start_date);
99            assert_eq!(end_date, dataset.end_date);
100        }
101
102        #[test]
103        fn with_extended_validity_period() {
104            let start_date = Date::from_ymd_opt(2019, 1, 1).unwrap();
105            let end_date = Date::from_ymd_opt(2019, 6, 30).unwrap();
106            let mut dataset = Dataset {
107                id: String::from("dataset_id"),
108                contributor_id: String::from("contributor_id"),
109                start_date: Date::from_ymd_opt(2019, 3, 1).unwrap(),
110                end_date: Date::from_ymd_opt(2019, 4, 30).unwrap(),
111                ..Default::default()
112            };
113            let service_validity_period = ValidityPeriod {
114                start_date,
115                end_date,
116            };
117            set_dataset_validity_period(&mut dataset, &service_validity_period);
118            assert_eq!(start_date, dataset.start_date);
119            assert_eq!(end_date, dataset.end_date);
120        }
121
122        #[test]
123        fn with_included_validity_period() {
124            let start_date = Date::from_ymd_opt(2019, 1, 1).unwrap();
125            let end_date = Date::from_ymd_opt(2019, 6, 30).unwrap();
126            let mut dataset = Dataset {
127                id: String::from("dataset_id"),
128                contributor_id: String::from("contributor_id"),
129                start_date,
130                end_date,
131                ..Default::default()
132            };
133            let service_validity_period = ValidityPeriod {
134                start_date: Date::from_ymd_opt(2019, 3, 1).unwrap(),
135                end_date: Date::from_ymd_opt(2019, 4, 30).unwrap(),
136            };
137            set_dataset_validity_period(&mut dataset, &service_validity_period);
138            assert_eq!(start_date, dataset.start_date);
139            assert_eq!(end_date, dataset.end_date);
140        }
141    }
142
143    mod compute_dataset_validity_period {
144        use super::super::*;
145        use crate::{
146            calendars, configuration::*, file_handler::PathFileHandler, model::Collections,
147            test_utils::*,
148        };
149
150        #[test]
151        fn test_compute_dataset_validity_period() {
152            let calendars_content = "service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date\n\
153                                 1,1,1,1,1,1,0,0,20180501,20180508\n\
154                                 2,0,0,0,0,0,1,1,20180514,20180520";
155
156            let calendar_dates_content = "service_id,date,exception_type\n\
157                                      2,20180520,2";
158
159            test_in_tmp_dir(|path| {
160                let mut handler = PathFileHandler::new(path.to_path_buf());
161                create_file_with_content(path, "calendar.txt", calendars_content);
162                create_file_with_content(path, "calendar_dates.txt", calendar_dates_content);
163
164                let mut collections = Collections::default();
165                let (_, mut dataset, _) = read_config(None::<&str>).unwrap();
166
167                calendars::manage_calendars(&mut handler, &mut collections).unwrap();
168                compute_dataset_validity_period(&mut dataset, &collections.calendars).unwrap();
169
170                assert_eq!(
171                    Dataset {
172                        id: "default_dataset".to_string(),
173                        contributor_id: "default_contributor".to_string(),
174                        start_date: chrono::NaiveDate::from_ymd_opt(2018, 5, 1).unwrap(),
175                        end_date: chrono::NaiveDate::from_ymd_opt(2018, 5, 19).unwrap(),
176                        dataset_type: None,
177                        extrapolation: false,
178                        desc: None,
179                        system: None,
180                    },
181                    dataset
182                );
183            });
184        }
185
186        #[test]
187        fn test_compute_dataset_validity_period_with_only_one_date() {
188            let calendars_content = "service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date\n\
189                                 1,1,1,1,1,1,0,0,20180501,20180501";
190
191            test_in_tmp_dir(|path| {
192                let mut handler = PathFileHandler::new(path.to_path_buf());
193                create_file_with_content(path, "calendar.txt", calendars_content);
194
195                let mut collections = Collections::default();
196                let (_, mut dataset, _) = read_config(None::<&str>).unwrap();
197
198                calendars::manage_calendars(&mut handler, &mut collections).unwrap();
199                compute_dataset_validity_period(&mut dataset, &collections.calendars).unwrap();
200
201                assert_eq!(
202                    Dataset {
203                        id: "default_dataset".to_string(),
204                        contributor_id: "default_contributor".to_string(),
205                        start_date: chrono::NaiveDate::from_ymd_opt(2018, 5, 1).unwrap(),
206                        end_date: chrono::NaiveDate::from_ymd_opt(2018, 5, 1).unwrap(),
207                        dataset_type: None,
208                        extrapolation: false,
209                        desc: None,
210                        system: None,
211                    },
212                    dataset
213                );
214            });
215        }
216    }
217}