gistools/readers/gtfs/schedule/timeframes.rs
1use crate::readers::csv::parse_csv_as_record;
2use alloc::{collections::BTreeMap, string::String};
3use s2json::MValueCompatible;
4
5/// # Timeframes
6///
7/// **Optional**
8/// Describes fare variations based on time of day, day of week, or specific dates.
9/// Timeframes can be associated with fare products in `fare_leg_rules.txt`.
10/// There must be no overlapping [start_time, end_time) intervals for the same
11/// `timeframe_group_id` and `service_id`.
12#[derive(Debug, Default, Clone, PartialEq, MValueCompatible)]
13pub struct GTFSTimeframe {
14 /// **Required**
15 /// Identifies a timeframe (or set of timeframes).
16 pub timeframe_group_id: String,
17 /// **Conditionally Required**
18 /// Beginning of a timeframe in HH:MM:SS format (<= 24:00:00).
19 /// The interval **includes** this time.
20 /// - If `end_time` is defined, `start_time` is required.
21 /// - If `end_time` is absent, `start_time` must be absent.
22 /// - If `start_time` is empty in the CSV, it is considered `00:00:00`.
23 pub start_time: Option<String>,
24 /// **Conditionally Required**
25 /// End of a timeframe in HH:MM:SS format (<= 24:00:00).
26 /// The interval **excludes** this time.
27 /// - If `start_time` is defined, `end_time` is required.
28 /// - If `start_time` is absent, `end_time` must be absent.
29 /// - If `end_time` is empty in the CSV, it is considered `24:00:00`.
30 pub end_time: Option<String>,
31 /// **Required**
32 /// Identifies a set of dates (`calendar.service_id` or `calendar_dates.service_id`)
33 /// when this timeframe is in effect.
34 pub service_id: String,
35}
36impl GTFSTimeframe {
37 /// Create a new GTFSTimeframe
38 pub fn new(source: &str) -> BTreeMap<String, GTFSTimeframe> {
39 let mut res = BTreeMap::new();
40 for record in parse_csv_as_record::<GTFSTimeframe>(source, None, None) {
41 res.insert(record.timeframe_group_id.clone(), record);
42 }
43 res
44 }
45}