You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/en/documentation/schedule/change-history/revision-history.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,9 @@
2
2
3
3
### Revision History
4
4
5
+
#### October 2025
6
+
* Added clarifications for `fare_transfer_rules.txt` and introduced a new `Local Time` field type. See [discussion](https://github.com/google/transit/pull/561).
7
+
5
8
#### September 2025
6
9
* Added `cemv_support` field in `agency.txt` and `routes.txt`. See [discussion](https://github.com/google/transit/pull/545).
7
10
* Added `stop_access` field in `stops.txt`. See [discussion](https://github.com/google/transit/pull/515).
Copy file name to clipboardExpand all lines: docs/en/documentation/schedule/reference.md
+8-7Lines changed: 8 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
## General Transit Feed Specification Reference
2
2
3
-
**Revised October 10, 2025. See [Revision History](../change-history/revision-history) for more details.**
3
+
**Revised October 28, 2025. See [Revision History](../change-history/revision-history) for more details.**
4
4
5
5
This document defines the format and structure of the files that comprise a GTFS dataset.
6
6
@@ -90,6 +90,7 @@ Presence conditions applicable to fields and files:
90
90
-**Integer** - An integer.
91
91
-**Phone number** - A phone number.
92
92
-**Time** - Time in the HH:MM:SS format (H:MM:SS is also accepted). The time is measured from "noon minus 12h" of the service day (effectively midnight except for days on which daylight savings time changes occur). For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS. <br> *Example: `14:30:00` for 2:30PM or `25:35:00` for 1:35AM on the next day.*
93
+
-**Local time** - Time in the HH:MM:SS format (H:MM:SS is also accepted). Represents a wall-clock time shown in the local time of the specified location.
93
94
-**Text** - A string of UTF-8 characters, which is aimed to be displayed and which must therefore be human readable.
94
95
-**Timezone** - TZ timezone from the [https://www.iana.org/time-zones](https://www.iana.org/time-zones). Timezone names never contain the space character but may contain an underscore. Refer to [http://en.wikipedia.org/wiki/List\_of\_tz\_zones](http://en.wikipedia.org/wiki/List\_of\_tz\_zones) for a list of valid values. <br> *Example: `Asia/Tokyo`, `America/Los_Angeles` or `Africa/Cairo`.*
95
96
-**URL** - A fully qualified URL that includes http:// or https://, and any special characters in the URL must be correctly escaped. See the following [http://www.w3.org/Addressing/URL/4\_URI\_Recommentations.html](http://www.w3.org/Addressing/URL/4\_URI\_Recommentations.html) for a description of how to create fully qualified URL values.
@@ -244,7 +245,7 @@ Primary key (`route_id`)
244
245
|`route_sort_order`| Non-negative integer | Optional | Orders the routes in a way which is ideal for presentation to customers. Routes with smaller `route_sort_order` values should be displayed first. |
245
246
|`continuous_pickup`| Enum |**Conditionally Forbidden**| Indicates that the rider can board the transit vehicle at any point along the vehicle’s travel path as described by [shapes.txt](#shapestxt), on every trip of the route. Valid options are: <br><br>`0` - Continuous stopping pickup. <br>`1` or empty - No continuous stopping pickup. <br>`2` - Must phone agency to arrange continuous stopping pickup. <br>`3` - Must coordinate with driver to arrange continuous stopping pickup. <br><br>Values for `routes.continuous_pickup` may be overridden by defining values in `stop_times.continuous_pickup` for specific `stop_time`s along the route. <br><br>**Conditionally Forbidden**:<br>- Any value other than `1` or empty is **Forbidden** if `stop_times.start_pickup_drop_off_window` or `stop_times.end_pickup_drop_off_window` are defined for any trip of this route.<br> - Optional otherwise. |
246
247
|`continuous_drop_off`| Enum |**Conditionally Forbidden**| Indicates that the rider can alight from the transit vehicle at any point along the vehicle’s travel path as described by [shapes.txt](#shapestxt), on every trip of the route. Valid options are: <br><br>`0` - Continuous stopping drop off. <br>`1` or empty - No continuous stopping drop off. <br>`2` - Must phone agency to arrange continuous stopping drop off. <br>`3` - Must coordinate with driver to arrange continuous stopping drop off. <br><br>Values for `routes.continuous_drop_off` may be overridden by defining values in `stop_times.continuous_drop_off` for specific `stop_time`s along the route. <br><br>**Conditionally Forbidden**:<br>- Any value other than `1` or empty is **Forbidden** if `stop_times.start_pickup_drop_off_window` or `stop_times.end_pickup_drop_off_window` are defined for any trip of this route.<br> - Optional otherwise. |
247
-
| `network_id` | ID | **Conditionally Forbidden** | Identifies a group of routes. Multiple rows in [routes.txt](#routestxt) may have the same `network_id`.<br><br>Conditionally Forbidden:<br>- **Forbidden** if the [route_networks.txt](#route_networkstxt) file exists.<br>- Optional otherwise.
248
+
| `network_id` | ID | **Conditionally Forbidden** | Identifies a group of routes. Multiple rows in [routes.txt](#routestxt) may have the same `network_id`.<br><br>Conditionally Forbidden:<br>- **Forbidden** if the [route_networks.txt](#route_networkstxt)or [networks.txt](#networkstxt)file exists.<br>- Optional otherwise.
248
249
| `cemv_support` | Enum | Optional | Indicates if riders can access a transit service (i.e., trip) associated with this route by using a contactless EMV (Europay, Mastercard, and Visa) card or mobile device as fare media at a fare validator (such as in pay-as-you-go or open-loop systems). This field does not indicate that cEMV can be used to purchase other fare products or to add value to another fare media. <br><br> Support for cEMVs should only be indicated if all services under this route are accessible with the use of cEMV cards or mobile devices as fare media. <br><br> Valid options are: <br><br>`0` or empty - No cEMV information for trips associated with this route. <br>`1` - Riders may use cEMVs as fare media for trips associated with this route. <br>`2` - cEMVs are not supported as fare media for trips associated with this route. <br><br> If both `agency.cemv_support` and `routes.cemv_support` are provided for the same service, the value in `routes.cemv_support` shall take precedence. <br><br> This field is independent of all other fare-related files and may be used separately. If there is conflicting information between this field and any fare-related file (such as `fare_media.txt`, `fare_products.txt`, or `fare_leg_rules.txt`), the information in those files shall take precedence over `agency.cemv_support`.
249
250
|
250
251
@@ -407,14 +408,14 @@ There must not be overlapping time intervals for the same `timeframe_group_id` a
407
408
| Field Name | Type | Presence | Description |
408
409
| ------ | ------ | ------ | ------ |
409
410
|`timeframe_group_id`| ID |**Required**| Identifies a timeframe or set of timeframes. |
410
-
|`start_time`|Time|**Conditionally Required**| Defines the beginning of a timeframe. The interval includes the start time.<br> Values greater than `24:00:00` are forbidden. An empty value in `start_time` is considered `00:00:00`. <br><br> Conditionally Required:<br> - **Required** if `timeframes.end_time` is defined.<br> - **Forbidden** otherwise |
411
-
|`end_time`|Time|**Conditionally Required**| Defines the end of a timeframe. The interval does not include the end time.<br> Values greater than `24:00:00` are forbidden. An empty value in `end_time` is considered `24:00:00`. <br><br> Conditionally Required:<br> - **Required** if `timeframes.start_time` is defined.<br> - **Forbidden** otherwise |
411
+
|`start_time`|Local time|**Conditionally Required**| Defines the beginning of a timeframe. The interval includes the start time.<br> Values greater than `24:00:00` are forbidden. An empty value in `start_time` is considered `00:00:00`. <br><br> Conditionally Required:<br> - **Required** if `timeframes.end_time` is defined.<br> - **Forbidden** otherwise |
412
+
|`end_time`|Local time|**Conditionally Required**| Defines the end of a timeframe. The interval does not include the end time.<br> Values greater than `24:00:00` are forbidden. An empty value in `end_time` is considered `24:00:00`. <br><br> Conditionally Required:<br> - **Required** if `timeframes.start_time` is defined.<br> - **Forbidden** otherwise |
412
413
|`service_id`| Foreign ID referencing `calendar.service_id` or `calendar_dates.service_id`|**Required**| Identifies a set of dates that a timeframe is in effect. |
413
414
414
415
#### Timeframe Local Time Semantics
415
416
- When evaluating a fare event’s time against [timeframes.txt](#timeframestxt), the event time is computed in local time using the local timezone, as determined by the `stop_timezone`, if specified, of the stop or parent station for the fare event. If not specified, the feed’s agency timezone should be used instead.
416
417
- The “current day” is the current date of the fare event’s time, computed relative to the local timezone. The “current day” may be different from the service day of a fare leg’s trip, especially for trips that extend past midnight.
417
-
- The “time-of-day” for the fare event is computed relative to “current day” using GTFS Time field-type semantics.
418
+
- The “time-of-day” for the fare event is computed relative to “current day” using GTFS Local time field-type semantics.
418
419
419
420
### rider_categories.txt
420
421
@@ -543,7 +544,7 @@ Fare rules for transfers between legs of travel defined in [`fare_leg_rules.txt`
543
544
544
545
To process the cost of a multi-leg journey:
545
546
546
-
1. The applicable fare leg groups defined in `fare_leg_rules.txt` should be determined for all individual legs of travel based on the rider’s journey.
547
+
1. The applicable fare leg groups defined in `fare_leg_rules.txt` should be determined for all individual legs or effective fare legs of travel based on the rider’s journey.
547
548
2. The file [fare_transfer_rules.txt](#fare_transfer_rulestxt) must be filtered by the fields that define the characteristics of the transfer, these fields are:
548
549
-`fare_transfer_rules.from_leg_group_id`
549
550
-`fare_transfer_rules.to_leg_group_id`<br/>
@@ -564,7 +565,7 @@ To process the cost of a multi-leg journey:
564
565
|`to_leg_group_id`| Foreign ID referencing `fare_leg_rules.leg_group_id`| Optional | Identifies a group of post-transfer fare leg rules.<br><br>If there are no matching `fare_transfer_rules.to_leg_group_id` values to the `leg_group_id` being filtered, empty `fare_transfer_rules.to_leg_group_id` will be matched by default.<br><br>An empty entry in `fare_transfer_rules.to_leg_group_id` corresponds to all leg groups defined under `fare_leg_rules.leg_group_id` excluding the ones listed under `fare_transfer_rules.to_leg_group_id`|
565
566
|`transfer_count`| Non-zero integer |**Conditionally Forbidden**| Defines how many consecutive transfers the transfer rule may be applied to.<br><br>Valid options are:<br>`-1` - No limit.<br>`1` or more - Defines how many transfers the transfer rule may span.<br><br>If a sub-journey matches multiple records with different `transfer_count`s, then the rule with the minimum `transfer_count` that is greater than or equal to the current transfer count of the sub-journey is to be selected.<br><br>Conditionally Forbidden:<br>- **Forbidden** if `fare_transfer_rules.from_leg_group_id` does not equal `fare_transfer_rules.to_leg_group_id`.<br>- **Required** if `fare_transfer_rules.from_leg_group_id` equals `fare_transfer_rules.to_leg_group_id`. |
566
567
|`duration_limit`| Positive integer | Optional | Defines the duration limit of the transfer.<br><br>Must be expressed in integer increments of seconds.<br><br>If there is no duration limit, `fare_transfer_rules.duration_limit` must be empty. |
567
-
|`duration_limit_type`| Enum |**Conditionally Required**| Defines the relative start and end of `fare_transfer_rules.duration_limit`.<br><br>Valid options are:<br>`0` - Between the departure fare validation of the current leg and the arrival fare validation of the next leg.<br>`1` - Between the departure fare validation of the current leg and the departure fare validation of the next leg.<br>`2` - Between the arrival fare validation of the current leg and the departure fare validation of the next leg.<br>`3` - Between the arrival fare validation of the current leg and the arrival fare validation of the next leg.<br><br>Conditionally Required:<br>- **Required** if `fare_transfer_rules.duration_limit` is defined.<br>- **Forbidden** if `fare_transfer_rules.duration_limit` is empty. |
568
+
| `duration_limit_type` | Enum | **Conditionally Required** | Defines the relative start and end of `fare_transfer_rules.duration_limit`.<br><br>Valid options are:<br>`0` - Between the departure fare validation of the first leg in transfer sub-journey and the arrival fare validation of the last leg in transfer sub-journey.<br>`1` - Between the departure fare validation of the first leg in transfer sub-journey and the departure fare validation of the last leg in transfer sub-journey.<br>`2` - Between the arrival fare validation of the first leg in transfer sub-journey and the departure fare validation of the last leg in transfer sub-journey.<br>`3` - Between the arrival fare validation of the first leg in transfer sub-journey and the arrival fare validation of the last leg in transfer sub-journey.<br><br>When a transfer rule with the same `from_leg_group_id` and `to_leg_group_id` is matched multiple times consecutively within a multi-leg journey, the `duration_limit` specified by the rule should be measured starting from the first matched leg.<br><br>Conditionally Required:<br>- **Required** if `fare_transfer_rules.duration_limit` is defined.<br>- **Forbidden** if `fare_transfer_rules.duration_limit` is empty. |
568
569
|`fare_transfer_type`| Enum |**Required**| Indicates the cost processing method of transferring between legs in a journey: <br> <br>Valid options are:<br>`0` - From-leg `fare_leg_rules.fare_product_id` plus `fare_transfer_rules.fare_product_id`; A + AB.<br>`1` - From-leg `fare_leg_rules.fare_product_id` plus `fare_transfer_rules.fare_product_id` plus to-leg `fare_leg_rules.fare_product_id`; A + AB + B.<br>`2` - `fare_transfer_rules.fare_product_id`; AB. <br><br>Cost processing interactions between multiple transfers in a journey:<br><br><table><thead><tr><th>`fare_transfer_type`</th><th>Processing A > B</th><th>Processing B > C</th></tr></thead><tbody><tr><td>`0`</td><td>A + AB</td><td>S + BC</td></tr><tr><td>`1`</td><td>A + AB +B</td><td>S + BC + C</td></tr><tr><td>`2`</td><td>AB</td><td>S + BC</td></tr></tbody></table>Where S indicates the total processed cost of the preceding leg(s) and transfer(s). |
569
570
|`fare_product_id`| Foreign ID referencing `fare_products.fare_product_id`| Optional | The fare product required to transfer between two fare legs. If empty, the cost of the transfer rule is 0.|
0 commit comments