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}