gistools/readers/gtfs/schedule/
frequencies.rs

1use crate::readers::csv::parse_csv_as_record;
2use alloc::{string::String, vec::Vec};
3use s2json::MValueCompatible;
4
5/// Indicates the type of service for a trip with frequencies:
6/// 0 or empty = Frequency-based trips
7/// 1 = Schedule-based trips (with identical headway)
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
9pub enum GTFSExactTimes {
10    /// 0 - Frequency-based trips
11    FrequencyBased = 0,
12    /// 1 - Schedule-based trips
13    ScheduleBased = 1,
14}
15impl From<i32> for GTFSExactTimes {
16    fn from(value: i32) -> Self {
17        match value {
18            1 => GTFSExactTimes::ScheduleBased,
19            _ => GTFSExactTimes::FrequencyBased,
20        }
21    }
22}
23
24/// # Frequency
25///
26/// **Optional**
27/// Defines headway-based (or compressed schedule-based) service for specific trips.
28/// Each record references a single trip and indicates:
29/// - A start/end time window
30/// - A headway (seconds between departures)
31/// - Whether it’s frequency-based (exact_times=0) or schedule-based (exact_times=1).
32///
33/// **Primary Key**: (`trip_id`, `start_time`)
34#[derive(Debug, Default, Clone, PartialEq, MValueCompatible)]
35pub struct GTFSFrequency {
36    /// **Required**
37    /// Identifies the trip (`trips.trip_id`) to which the specified headway of service applies.
38    pub trip_id: String,
39    /// **Required**
40    /// Time at which the first vehicle departs from the trip’s first stop
41    /// with the specified headway (HH:MM:SS, can exceed 24:00:00 if overnight).
42    pub start_time: String,
43    /// **Required**
44    /// Time at which service changes or ends (HH:MM:SS, can exceed 24:00:00 if overnight).
45    pub end_time: String,
46    /// **Required**
47    /// Headway in seconds between departures from the same stop for this trip,
48    /// during [start_time, end_time).
49    pub headway_secs: i64,
50    /// **Optional**
51    /// Whether this is frequency-based or schedule-based service.
52    /// - 0 or empty = Frequency-based
53    /// - 1 = Schedule-based
54    pub exact_times: Option<i32>, // GTFSExactTimes;
55}
56impl GTFSFrequency {
57    /// Create a new GTFSFrequency
58    pub fn new(source: &str) -> Vec<GTFSFrequency> {
59        let mut res = Vec::new();
60        for record in parse_csv_as_record::<GTFSFrequency>(source, None, None) {
61            res.push(record);
62        }
63        res
64    }
65    /// Get the exact times
66    pub fn exact_times(&self) -> Option<GTFSExactTimes> {
67        self.exact_times.map(GTFSExactTimes::from)
68    }
69}