[GTFS-Fares v2] Add duration limit to fare_leg_join_rules.txt#639
[GTFS-Fares v2] Add duration limit to fare_leg_join_rules.txt#639skalexch wants to merge 3 commits into
Conversation
|
Hi @BodoMinea @jfabi, @felixguendling, @jasonad123, @halbertram @skinkie @bdferris-v2 @miklcct @jll01 @davidlewis-ito Following previous Fares Working Group discussions in 2025, we have decoupled the duration limit fields from the distance-based fares proposal into a standalone Pull Request. We believe this addition is broadly useful for various fare structures beyond distance-based ones, especially for simplifying transfer definitions. We are planning to initiate a "vote-to-test" in mid-July. Thank you in advance for your contribution! |
| | `from_stop_id` | Foreign ID referencing `stops.stop_id`| **Conditionally Required** | Matches a pre-transfer leg that ends at the specified stop (`location_type=0` or empty) or station (`location_type=1`).<br><br>Conditionally Required:<br> - **Required** if `to_stop_id` is defined.<br> - Optional otherwise. | | ||
| | `to_stop_id` | Foreign ID referencing `stops.stop_id`| **Conditionally Required** | Matches a post-transfer leg that starts at the specified stop (`location_type=0` or empty) or station (`location_type=1`).<br><br>Conditionally Required:<br> - **Required** if `from_stop_id` is defined.<br> - Optional otherwise. | | ||
| | `duration_limit` | Positive integer | **Optional** | Defines the duration limit of the transfer between the legs that constitute the effective leg. <br><br>Must be expressed in integer increments of seconds.<br><br>If there is no duration limit, `fare_leg_join_rules.duration_limit` must be empty. | | ||
| | `duration_limit_type` | Enum | **Conditionally Required** | Defines the relative start and end of `fare_leg_join_rules.duration_limit`.<br><br>Valid options are:<br>`0` - Between the departure fare validation of the first leg in the effective leg and the arrival fare validation of the last leg in the effective leg.<br>`1` - Between the departure fare validation of the first leg in the effective leg and the departure fare validation of the last leg in the effective leg.<br>`2` - Between the arrival fare validation of the first leg in the effective leg and the departure fare validation of the last leg in the effective leg.<br>`3` - Between the arrival fare validation of the first leg in the effective leg and the arrival fare validation of the last leg in the effective leg.<br><br>When an effective leg with the same `from_network_id` and `to_network_id` is matched multiple times consecutively within a multi-leg journey, the `duration_limit` specified by the effective leg should be measured starting from the first matched leg.<br><br>Conditionally Required:<br>- **Required** if `fare_leg_join_rules.duration_limit` is defined.<br>- **Forbidden** if `fare_leg_join_rules.duration_limit` is empty. | |
There was a problem hiding this comment.
The router doesn't know when exactly the ticket will be validated (i.e. walking time between fare gate and departure/arrival of the vehicle vice versa).
So I would change departure fare validation to departure time (same for arrival).
There was a problem hiding this comment.
Thanks for sharing your feedback @felixguendling. In fact, the wording is copied verbatim from the definition of duration_limit_type in fare_transfer_rules.txt. Therefore, both need to be changed if need be.
However, this was talked about in a few 2023 Fare Working Group Meetings when timeframes were being discussed.
The consensus seemed to be that in a real-world situation, the timeframe (or fare product transfer duration since it's similar) starts when tapping on the bus (0 min of delay) or at a fare gate (a few minutes of delay based on the size of the station, how long the rider will linger or if they are taking the first train). So the time limit for a fare product starts counting down when the rider taps. Therefore, the wording "fare validation" accurately describes the mechanism in real life.
In terms of router behaviour, there are ways of approximating the duration of the journey's walking-legs to be able to compare directly with duration_limit, among others:
- Using pathways if they exist.
- Approximating in-station walking time using OSM.
- Providing default in-station walking times.
This is left to trip planners to choose how they approximate it.
There was a problem hiding this comment.
This is left to trip planners to choose how they approximate it.
A good standard doesn't leave room for interpretation.
So I would propose to:
- either state that the timetable times (arrival / departure) can be used as they are. E.g. because the ticketing system itself leaves some room for walking by having more permissive limits or an average walking time is already subtracted from the duration limit
- or it's clearly stated that in-station walking times have to be calculated using GTFS pathways from fare gates (probably
pathway_mode=6?) to tracks (or vice versa for arrival) - which would require a Fares v2 feed to always come with proper GTFS pathways.
I think that adding a duration_limit without a clearly defined way to measure durations (e.g. based on GTFS pathways; OSM is out-of-scope here I guess) isn't helpful if you want to consume the data.
Summary
This proposal:
duration_limitandduration_limit_typeto join rules infare_leg_join_rules.txt.fare_leg_join_rules.txtorfare_transfer_rules.txt.fare_leg_join_rules.txtandfare_transfer_rules.txtfor joins based onnetwork_id.Describe the Problem
This was part of the distance-based fares proposal. We decided to separate it in its own proposal for a few reasons:
fare_leg_join_rules.txt.Use Cases
This is mainly to allow the usage of
fare_leg_join_rules.txtas a simpler way to define transfers in fare structures such as:Proposed Solution
Adding
duration_limitandduration_limit_typeto join rules infare_leg_join_rules.txtand forbidding overlap betweenfare_leg_join_rules.txtandfare_transfer_rules.txtfor joins based onnetwork_id.Type of change
GTFS Schedule
GTFS Realtime
Additional Information
More research can be found in the research document.
Proposed Discussion Period
We propose a discussion period of at least 2 weeks before starting an official review period. We will start the review period later in June.
Testing Details
Proposal Update Tracker
Checklist