diff --git a/gtfs/CHANGES.md b/gtfs/CHANGES.md index c537d1f3..6a404608 100644 --- a/gtfs/CHANGES.md +++ b/gtfs/CHANGES.md @@ -13,7 +13,7 @@ The official specification, reference and documentation are written in English. - At any point in time the advocate can claim proposal abandoned. 1. The advocate can call for a vote on a version of the proposal at any point in time following the initial 7-day interval required for discussion. - Before calling for a vote, at least one GTFS producer and one GTFS consumer should implement the proposed change. It is expected that the GTFS producer(s) include the change in a public-facing GTFS feed and provide a link to that data within the pull request comments, and that the GTFS consumer(s) provides a link in the pull request comments to an application that is utilizing the change in a non-trivial manner (i.e, it is supporting new or improved functionality). -1. Vote lasts the minimum period sufficient to cover 7 full calendar days and 5 full Swiss business days. Vote ends at 23:59:59 UTC. +1. Vote lasts the minimum period sufficient to cover 14 full calendar days. Vote ends at 23:59:59 UTC. - The advocate should announce the specific end time at the start of the vote. - During voting period only editorial changes to the proposal are allowed (typos, wording may change as long as it does not change the meaning). - Anyone is allowed to vote yes/no in a form of comment to the pull request, and votes can be changed until the end of the voting period. @@ -53,6 +53,16 @@ Every new feature adds complexity to the creation and reading of feeds. Therefor ### Revision History +#### August 2023 +* Add fare_media_type=1. See [discussion](https://github.com/google/transit/pull/385). + +#### July 2023 +* Forbid subfolders in GTFS files. See [discussion](https://github.com/google/transit/pull/379). +* Added variable fares by time or day. See [discussion](https://github.com/google/transit/pull/357). +* Clarify implied timezone in stop_times.txt. See [discussion](https://github.com/google/transit/pull/378). +* Specify stop times shape_dist_traveled must not exceed the trip shape's maximum distance. See [discussion](https://github.com/google/transit/pull/380). +* Best practices: add recommended presence. See [discussion](https://github.com/google/transit/pull/386). + #### March 14, 2023 * Added fare media. See [discussion](https://github.com/google/transit/pull/355). diff --git a/gtfs/spec/en/inlining.svg b/gtfs/spec/en/inlining.svg new file mode 100644 index 00000000..616575da --- /dev/null +++ b/gtfs/spec/en/inlining.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index a917e601..d4a5dbda 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -19,6 +19,7 @@ This document defines the format and structure of the files that comprise a GTFS - [calendar\_dates.txt](#calendar_datestxt) - [fare\_attributes.txt](#fare_attributestxt) - [fare\_rules.txt](#fare_rulestxt) + - [timeframes.txt](#timeframestxt) - [fare\_media.txt](#fare_mediatxt) - [fare\_products.txt](#fare_productstxt) - [fare\_leg\_rules.txt](#fare_leg_rulestxt) @@ -60,6 +61,7 @@ Presence conditions applicable to fields and files: * **Optional** - The field or file may be omitted from the dataset. * **Conditionally Required** - The field or file must be included under conditions outlined in the field or file description. * **Conditionally Forbidden** - The field or file must not be included under conditions outlined in the field or file description. +* **Recommended** - The field or file may be omitted from the dataset, but it is a best practice to include it. Before omitting this field or file, the best practice should be carefully evaluated and the full implications of omission should be understood. ### Field Types @@ -76,7 +78,7 @@ Presence conditions applicable to fields and files: - **Float** - A floating point number. - **Integer** - An integer. - **Phone number** - A phone number. -- **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, enter the time as a value greater than 24:00:00 in HH:MM:SS local time for the day on which the trip schedule begins.
*Example: `14:30:00` for 2:30PM or `25:35:00` for 1:35AM on the next day.* +- **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.
*Example: `14:30:00` for 2:30PM or `25:35:00` for 1:35AM on the next day.* - **Text** - A string of UTF-8 characters, which is aimed to be displayed and which must therefore be human readable. - **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.
*Example: `Asia/Tokyo`, `America/Los_Angeles` or `Africa/Cairo`.* - **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. @@ -110,6 +112,7 @@ This specification defines the following files: | [calendar_dates.txt](#calendar_datestxt) | **Conditionally Required** | Exceptions for the services defined in the [calendar.txt](#calendartxt).

Conditionally Required:
- **Required** if [calendar.txt](#calendartxt) is omitted. In which case [calendar_dates.txt](#calendar_datestxt) must contain all dates of service.
- Optional otherwise. | | [fare_attributes.txt](#fare_attributestxt) | Optional | Fare information for a transit agency's routes. | | [fare_rules.txt](#fare_rulestxt) | Optional | Rules to apply fares for itineraries. | +| [timeframes.txt](#timeframestxt) | Optional | Date and time periods to use in fare rules for fares that depend on date and time factors. | | [fare_media.txt](#fare_mediatxt) | Optional | To describe the fare media that can be employed to use fare products.

File [fare_media.txt](#fare_mediatxt) describes concepts that are not represented in [fare_attributes.txt](#fare_attributestxt) and [fare_rules.txt](#fare_rulestxt). As such, the use of [fare_media.txt](#fare_mediatxt) is entirely separate from files [fare_attributes.txt](#fare_attributestxt) and [fare_rules.txt](#fare_rulestxt). | | [fare_products.txt](#fare_productstxt) | Optional | To describe the different types of tickets or fares that can be purchased by riders.

File [fare_products.txt](#fare_productstxt) describes fare products that are not represented in [fare_attributes.txt](#fare_attributestxt) and [fare_rules.txt](#fare_rulestxt). As such, the use of [fare_products.txt](#fare_productstxt) is entirely separate from files [fare_attributes.txt](#fare_attributestxt) and [fare_rules.txt](#fare_rulestxt). | | [fare_leg_rules.txt](#fare_leg_rulestxt) | Optional | Fare rules for individual legs of travel.

File [fare_leg_rules.txt](#fare_leg_rulestxt) provides a more detailed method for modeling fare structures. As such, the use of [fare_leg_rules.txt](#fare_leg_rulestxt) is entirely separate from files [fare_attributes.txt](#fare_attributestxt) and [fare_rules.txt](#fare_rulestxt). | @@ -141,7 +144,7 @@ The following example demonstrates how a field value would appear in a comma-del * Extra spaces between fields or field names should be removed. Many parsers consider the spaces to be part of the value, which may cause errors. * Each line must end with a CRLF or LF linebreak character. * Files should be encoded in UTF-8 to support all Unicode characters. Files that include the Unicode byte-order mark (BOM) character are acceptable. See [http://unicode.org/faq/utf_bom.html#BOM](http://unicode.org/faq/utf_bom.html#BOM) for more information on the BOM character and UTF-8. -* All dataset files must be zipped together. +* All dataset files must be zipped together. The files must reside at the root level directly, not in a subfolder. ## Field Definitions @@ -153,7 +156,7 @@ Primary key (`agency_id`) | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | -| `agency_id` | Unique ID | **Conditionally Required** | Identifies a transit brand which is often synonymous with a transit agency. Note that in some cases, such as when a single agency operates multiple separate services, agencies and brands are distinct. This document uses the term "agency" in place of "brand". A dataset may contain data from multiple agencies.

Conditionally Required:
- **Required** when the dataset contains data for multiple transit agencies.
- Optional otherwise. | +| `agency_id` | Unique ID | **Conditionally Required** | Identifies a transit brand which is often synonymous with a transit agency. Note that in some cases, such as when a single agency operates multiple separate services, agencies and brands are distinct. This document uses the term "agency" in place of "brand". A dataset may contain data from multiple agencies.

Conditionally Required:
- **Required** when the dataset contains data for multiple transit agencies.
- Recommended otherwise. | | `agency_name` | Text | **Required** | Full name of the transit agency. | | `agency_url` | URL | **Required** | URL of the transit agency. | | `agency_timezone` | Timezone | **Required** | Timezone where the transit agency is located. If multiple agencies are specified in the dataset, each must have the same `agency_timezone`. | @@ -196,8 +199,8 @@ Primary key (`route_id`) | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | | `route_id` | Unique ID | **Required** | Identifies a route. | -| `agency_id` | Foreign ID referencing `agency.agency_id` | **Conditionally Required** | Agency for the specified route.

Conditionally Required:
- **Required** if multiple agencies are defined in [agency.txt](#agency).
- Optional otherwise. | -| `route_short_name` | Text | **Conditionally Required** | Short name of a route. Often a short, abstract identifier (e.g., "32", "100X", "Green") that riders use to identify a route. Both `route_short_name` and `route_long_name` may be defined.

Conditionally Required:
- **Required** if `routes.route_long_name` is empty.
- Optional otherwise. | +| `agency_id` | Foreign ID referencing `agency.agency_id` | **Conditionally Required** | Agency for the specified route.

Conditionally Required:
- **Required** if multiple agencies are defined in [agency.txt](#agency).
- Recommended otherwise. | +| `route_short_name` | Text | **Conditionally Required** | Short name of a route. Often a short, abstract identifier (e.g., "32", "100X", "Green") that riders use to identify a route. Both `route_short_name` and `route_long_name` may be defined.

Conditionally Required:
- **Required** if `routes.route_long_name` is empty.
- Recommended if there is a brief service designation. This should be the commonly-known passenger name of the service, and should be no longer than 12 characters. | | `route_long_name` | Text | **Conditionally Required** | Full name of a route. This name is generally more descriptive than the `route_short_name` and often includes the route's destination or stop. Both `route_short_name` and `route_long_name` may be defined.

Conditionally Required:
- **Required** if `routes.route_short_name` is empty.
- Optional otherwise. | | `route_desc` | Text | Optional | Description of a route that provides useful, quality information. Should not be a duplicate of `route_short_name` or `route_long_name`.
_Example: "A" trains operate between Inwood-207 St, Manhattan and Far Rockaway-Mott Avenue, Queens at all times. Also from about 6AM until about midnight, additional "A" trains operate between Inwood-207 St and Lefferts Boulevard (trains typically alternate between Lefferts Blvd and Far Rockaway)._ | | `route_type` | Enum | **Required** | Indicates the type of transportation used on a route. Valid options are:

`0` - Tram, Streetcar, Light rail. Any light rail or street level system within a metropolitan area.
`1` - Subway, Metro. Any underground rail system within a metropolitan area.
`2` - Rail. Used for intercity or long-distance travel.
`3` - Bus. Used for short- and long-distance bus routes.
`4` - Ferry. Used for short- and long-distance boat service.
`5` - Cable tram. Used for street-level rail cars where the cable runs beneath the vehicle (e.g., cable car in San Francisco).
`6` - Aerial lift, suspended cable car (e.g., gondola lift, aerial tramway). Cable transport where cabins, cars, gondolas or open chairs are suspended by means of one or more cables.
`7` - Funicular. Any rail system designed for steep inclines.
`11` - Trolleybus. Electric buses that draw power from overhead wires using poles.
`12` - Monorail. Railway in which the track consists of a single rail or a beam. | @@ -254,8 +257,8 @@ Primary key (`trip_id`, `stop_sequence`) | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | | `trip_id` | Foreign ID referencing `trips.trip_id` | **Required** | Identifies a trip. | -| `arrival_time` | Time | **Conditionally Required** | Arrival time at the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`).

If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS local time for the day on which the trip schedule begins.

If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

Conditionally Required:
- **Required** for the first and last stop in a trip (defined by `stop_times.stop_sequence`).
- **Required** for `timepoint=1`.
- Optional otherwise.| -| `departure_time` | Time | **Conditionally Required** | Departure time from the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`).

If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS local time for the day on which the trip schedule begins.

If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

Conditionally Required:
- **Required** for `timepoint=1`.
- Optional otherwise.| | +| `arrival_time` | Time | **Conditionally Required** | Arrival time at the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`) in the time zone specified by `agency.agency_timezone`, not `stops.stop_timezone`.

If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS.

If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

Conditionally Required:
- **Required** for the first and last stop in a trip (defined by `stop_times.stop_sequence`).
- **Required** for `timepoint=1`.
- Optional otherwise.| +| `departure_time` | Time | **Conditionally Required** | Departure time from the stop (defined by `stop_times.stop_id`) for a specific trip (defined by `stop_times.trip_id`) in the time zone specified by `agency.agency_timezone`, not `stops.stop_timezone`.

If there are not separate times for arrival and departure at a stop, `arrival_time` and `departure_time` should be the same.

For times occurring after midnight on the service day, enter the time as a value greater than 24:00:00 in HH:MM:SS.

If exact arrival and departure times (`timepoint=1` or empty) are not available, estimated or interpolated arrival and departure times (`timepoint=0`) should be provided.

Conditionally Required:
- **Required** for `timepoint=1`.
- Optional otherwise.| | | `stop_id` | Foreign ID referencing `stops.stop_id` | **Required** | Identifies the serviced stop. All stops serviced during a trip must have a record in [stop_times.txt](#stop_timestxt). Referenced locations must be stops/platforms, i.e. their `stops.location_type` value must be `0` or empty. A stop may be serviced multiple times in the same trip, and multiple trips and routes may service the same stop. | | `stop_sequence` | Non-negative integer | **Required** | Order of stops for a particular trip. The values must increase along the trip but do not need to be consecutive.
*Example: The first location on the trip could have a `stop_sequence`=`1`, the second location on the trip could have a `stop_sequence`=`23`, the third location could have a `stop_sequence`=`40`, and so on.* | | `stop_headsign` | Text | Optional | Text that appears on signage identifying the trip's destination to riders. This field overrides the default `trips.trip_headsign` when the headsign changes between stops. If the headsign is displayed for an entire trip, `trips.trip_headsign` should be used instead.

A `stop_headsign` value specified for one `stop_time` does not apply to subsequent `stop_time`s in the same trip. If you want to override the `trip_headsign` for multiple `stop_time`s in the same trip, the `stop_headsign` value must be repeated in each `stop_time` row. | @@ -263,8 +266,8 @@ Primary key (`trip_id`, `stop_sequence`) | `drop_off_type` | Enum | Optional | Indicates drop off method. Valid options are:

`0` or empty - Regularly scheduled drop off.
`1` - No drop off available.
`2` - Must phone agency to arrange drop off.
`3` - Must coordinate with driver to arrange drop off. | | `continuous_pickup` | Enum | Optional | Indicates that the rider can board the transit vehicle at any point along the vehicle’s travel path as described by `shapes.txt`, from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. Valid options are:

`0` - Continuous stopping pickup.
`1` or empty - No continuous stopping pickup.
`2` - Must phone agency to arrange continuous stopping pickup.
`3` - Must coordinate with driver to arrange continuous stopping pickup.

If this field is populated, it overrides any continuous pickup behavior defined in `routes.txt`. If this field is empty, the `stop_time` inherits any continuous pickup behavior defined in `routes.txt`. | | `continuous_drop_off` | Enum | Optional | Indicates that the rider can alight from the transit vehicle at any point along the vehicle’s travel path as described by `shapes.txt`, from this `stop_time` to the next `stop_time` in the trip’s `stop_sequence`. Valid options are:

`0` - Continuous stopping drop off.
`1` or empty - No continuous stopping drop off.
`2` - Must phone agency to arrange continuous stopping drop off.
`3` - Must coordinate with driver to arrange continuous stopping drop off.

If this field is populated, it overrides any continuous drop-off behavior defined in `routes.txt`. If this field is empty, the `stop_time` inherits any continuous drop-off behavior defined in `routes.txt`. | -| `shape_dist_traveled` | Non-negative float | Optional | Actual distance traveled along the associated shape, from the first stop to the stop specified in this record. This field specifies how much of the shape to draw between any two stops during a trip. Must be in the same units used in [shapes.txt](#shapestxt). Values used for `shape_dist_traveled` must increase along with `stop_sequence`; they must not be used to show reverse travel along a route.
*Example: If a bus travels a distance of 5.25 kilometers from the start of the shape to the stop,`shape_dist_traveled`=`5.25`.*| -| `timepoint` | Enum | Optional | Indicates if arrival and departure times for a stop are strictly adhered to by the vehicle or if they are instead approximate and/or interpolated times. This field allows a GTFS producer to provide interpolated stop-times, while indicating that the times are approximate. Valid options are:

`0` - Times are considered approximate.
`1` or empty - Times are considered exact. | +| `shape_dist_traveled` | Non-negative float | Optional | Actual distance traveled along the associated shape, from the first stop to the stop specified in this record. This field specifies how much of the shape to draw between any two stops during a trip. Must be in the same units used in [shapes.txt](#shapestxt). Values used for `shape_dist_traveled` must increase along with `stop_sequence`; they must not be used to show reverse travel along a route.

Recommended for routes that have looping or inlining (the vehicle crosses or travels over the same portion of alignment in one trip). See [`shapes.shape_dist_traveled`](#shapestxt).
*Example: If a bus travels a distance of 5.25 kilometers from the start of the shape to the stop,`shape_dist_traveled`=`5.25`.*| +| `timepoint` | Enum | Recommended | Indicates if arrival and departure times for a stop are strictly adhered to by the vehicle or if they are instead approximate and/or interpolated times. This field allows a GTFS producer to provide interpolated stop-times, while indicating that the times are approximate. Valid options are:

`0` - Times are considered approximate.
`1` or empty - Times are considered exact. | ### calendar.txt @@ -320,7 +323,7 @@ There are two modelling options for describing fares. GTFS-Fares V1 is the legac | `currency_type` | Currency code | **Required** | Currency used to pay the fare. | | `payment_method` | Enum | **Required** | Indicates when the fare must be paid. Valid options are:

`0` - Fare is paid on board.
`1` - Fare must be paid before boarding. | | `transfers` | Enum | **Required** | Indicates the number of transfers permitted on this fare. Valid options are:

`0` - No transfers permitted on this fare.
`1` - Riders may transfer once.
`2` - Riders may transfer twice.
empty - Unlimited transfers are permitted. | -| `agency_id` | Foreign ID referencing `agency.agency_id` | **Conditionally Required** | Identifies the relevant agency for a fare.

Conditionally Required:
- **Required** if multiple agencies are defined in `agency.txt`.
- Optional otherwise. | +| `agency_id` | Foreign ID referencing `agency.agency_id` | **Conditionally Required** | Identifies the relevant agency for a fare.

Conditionally Required:
- **Required** if multiple agencies are defined in `agency.txt`.
- Recommended otherwise. | | `transfer_duration` | Non-negative integer | Optional | Length of time in seconds before a transfer expires. When `transfers`=`0` this field may be used to indicate how long a ticket is valid for or it may be left empty. | ### fare_rules.txt @@ -345,6 +348,27 @@ For examples that demonstrate how to specify a fare structure with [fare_rules.t | `destination_id` | Foreign ID referencing `stops.zone_id` | Optional | Identifies a destination zone. If a fare class has multiple destination zones, create a record in [fare_rules.txt](#fare_rules.txt) for each `destination_id`.
*Example: The `origin_id` and `destination_id` fields could be used together to specify that fare class "b" is valid for travel between zones 3 and 4, and for travel between zones 3 and 5, the [fare_rules.txt](#fare_rules.txt) file would contain these records for the fare class:*
`fare_id,...,origin_id,destination_id`
`b,...,3,4`
`b,...,3,5` | | `contains_id` | Foreign ID referencing `stops.zone_id` | Optional | Identifies the zones that a rider will enter while using a given fare class. Used in some systems to calculate correct fare class.
*Example: If fare class "c" is associated with all travel on the GRT route that passes through zones 5, 6, and 7 the [fare_rules.txt](#fare_rules.txt) would contain these records:*
`fare_id,route_id,...,contains_id`
`c,GRT,...,5`
`c,GRT,...,6`
`c,GRT,...,7`
*Because all `contains_id` zones must be matched for the fare to apply, an itinerary that passes through zones 5 and 6 but not zone 7 would not have fare class "c". For more detail, see [https://code.google.com/p/googletransitdatafeed/wiki/FareExamples](https://code.google.com/p/googletransitdatafeed/wiki/FareExamples) in the GoogleTransitDataFeed project wiki.* | +### timeframes.txt + +File: **Optional** + +Primary key (*) + +Used to describe fares that can vary based on the time of day, the day of the week, or a particular day in the year. Timeframes can be associated with fare products in `fare_leg_rules.txt`.
+There must not be overlapping time intervals for the same `timeframe_group_id` and `service_id` values. + +| Field Name | Type | Presence | Description | +| ------ | ------ | ------ | ------ | +| `timeframe_group_id` | ID | **Required** | Identifies a timeframe or set of timeframes. | +| `start_time` | Time | **Conditionally Required** | Defines the beginning of a timeframe. The interval includes the start time.
Values greater than `24:00:00` are forbidden. An empty value in `start_time` is considered `00:00:00`.

Conditionally Required:
- **Required** if `timeframes.end_time` is defined.
- **Forbidden** otherwise | +| `end_time` | Time | **Conditionally Required** | Defines the end of a timeframe. The interval does not include the end time.
Values greater than `24:00:00` are forbidden. An empty value in `end_time` is considered `24:00:00`.

Conditionally Required:
- **Required** if `timeframes.start_time` is defined.
- **Forbidden** otherwise | +| `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. | + +#### Timeframe Local Time Semantics +- When evaluating a fare event’s time against `timeframes.txt`, 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. +- 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. +- The “time-of-day” for the fare event is computed relative to “current day” using GTFS Time field-type semantics. + ### fare_media.txt File: **Optional** @@ -357,7 +381,7 @@ To describe the different fare media that can be employed to use fare products. | ------ | ------ | ------ | ------ | | `fare_media_id` | Unique ID | **Required** | Identifies a fare media. | | `fare_media_name` | Text | Optional | Name of the fare media.

For fare media which are transit cards (`fare_media_type =2`) or mobile apps (`fare_media_type =4`), the `fare_media_name` should be included and should match the rider-facing name used by the organizations delivering them. | -| `fare_media_type` | Enum | **Required** | The type of fare media. Valid options are:

`0` - None. Used when there is no fare media involved in purchasing or validating a fare product, such as paying cash to a driver or conductor with no physical ticket provided.
`2` - Physical transit card that has stored tickets, passes or monetary value.
`3` - cEMV (contactless Europay, Mastercard and Visa) as an open-loop token container for account-based ticketing.
`4` - Mobile app that have stored virtual transit cards, tickets, passes, or monetary value.| +| `fare_media_type` | Enum | **Required** | The type of fare media. Valid options are:

`0` - None. Used when there is no fare media involved in purchasing or validating a fare product, such as paying cash to a driver or conductor with no physical ticket provided.
`1` - Physical paper ticket that allows a passenger to take either a certain number of pre-purchased trips or unlimited trips within a fixed period of time.
`2` - Physical transit card that has stored tickets, passes or monetary value.
`3` - cEMV (contactless Europay, Mastercard and Visa) as an open-loop token container for account-based ticketing.
`4` - Mobile app that have stored virtual transit cards, tickets, passes, or monetary value.| ### fare_products.txt @@ -380,7 +404,7 @@ To describe the different types of tickets or fares that can be purchased by rid File: **Optional** -Primary Key (`network_id, from_area_id, to_area_id, fare_product_id`) +Primary Key (`network_id, from_area_id, to_area_id, from_timeframe_group_id, to_timeframe_group_id, fare_product_id`) Fare rules for individual legs of travel. @@ -391,14 +415,18 @@ To process the cost of a leg: 1. The file `fare_leg_rules.txt` must be filtered by the fields that define the characteristics of travel, these fields are: - `fare_leg_rules.network_id` - `fare_leg_rules.from_area_id` - - `fare_leg_rules.to_area_id`
+ - `fare_leg_rules.to_area_id` + - `fare_leg_rules.from_timeframe_group_id` + - `fare_leg_rules.to_timeframe_group_id`

2. If the leg exactly matches a record in `fare_leg_rules.txt` based on the characteristics of travel, that record must be processed to determine the cost of the leg. +
+ 3. If no exact matches are found, then empty entries in `fare_leg_rules.network_id`, `fare_leg_rules.from_area_id`, and `fare_leg_rules.to_area_id` must be checked to process the cost of the leg: - An empty entry in `fare_leg_rules.network_id` corresponds to all networks defined in `routes.txt` excluding the ones listed under `fare_leg_rules.network_id` - An empty entry in `fare_leg_rules.from_area_id` corresponds to all areas defined in `areas.area_id` excluding the ones listed under `fare_leg_rules.from_area_id` - - An empty entry in `fare_leg_rules.to_area_id` corresponds to all areas defined in `areas.area_id` excluding the ones listed under `fare_leg_rules.to_area_id`
+ - An empty entry in `fare_leg_rules.to_area_id` corresponds to all areas defined in `areas.area_id` excluding the ones listed under `fare_leg_rules.to_area_id`
4. If the leg does not match any of the rules described above, then the fare is unknown. @@ -411,6 +439,8 @@ To process the cost of a leg: | `network_id` | Foreign ID referencing `routes.network_id` | Optional | Identifies a route network that applies for the fare leg rule.

If there are no matching `fare_leg_rules.network_id` values to the `network_id` being filtered, empty `fare_leg_rules.network_id` will be matched by default.

An empty entry in `fare_leg_rules.network_id` corresponds to all networks defined in `routes.txt` excluding the ones listed under `fare_leg_rules.network_id` | | `from_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies a departure area.

If there are no matching `fare_leg_rules.from_area_id` values to the `area_id` being filtered, empty `fare_leg_rules.from_area_id` will be matched by default.

An empty entry in `fare_leg_rules.from_area_id` corresponds to all areas defined in `areas.area_id` excluding the ones listed under `fare_leg_rules.from_area_id` | | `to_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies an arrival area.

If there are no matching `fare_leg_rules.to_area_id` values to the `area_id` being filtered, empty `fare_leg_rules.to_area_id` will be matched by default.

An empty entry in `fare_leg_rules.to_area_id` corresponds to all areas defined in `areas.area_id` excluding the ones listed under `fare_leg_rules.to_area_id` | +| `from_timeframe_group_id` | Foreign ID referencing `timeframes.timeframe_group_id` | Optional | Defines the timeframe for the fare validation event at the start of the fare leg.

The “start time” of the fare leg is the time at which the event is scheduled to occur. For example, the time could be the scheduled departure time of a bus at the start of a fare leg where the rider boards and validates their fare. For the rule matching semantics below, the start time is computed in local time, as determined by [Local Time Semantics](#localtimesemantics) of [timeframes.txt](#timeframestxt). The stop or station of the fare leg’s departure event should be used for timezone resolution, where appropriate.

For a fare leg rule that specifies a `from_timeframe_group_id`, that rule will match a particular leg if there exists at least one record in `timeframes.txt` where all of the following conditions are true
- The value of `timeframe_group_id` is equal to the `from_timeframe_group_id` value.
- The set of days identified by the record’s `service_id` contains the “current day” of the fare leg’s start time.
- The “time-of-day” of the fare leg's start time is greater than or equal to the record’s `timeframes.start_time` value and less than the `timeframes.end_time` value.

An empty `fare_leg_rules.from_timeframe_group_id` indicates that the start time of the leg does not affect the matching of this rule. | +| `to_timeframe_group_id` | Foreign ID referencing `timeframes.timeframe_group_id` | Optional | Defines the timeframe for the fare validation event at the end of the fare leg.

The “end time” of the fare leg is the time at which the event is scheduled to occur. For example, the time could be the scheduled arrival time of a bus at the end of a fare leg where the rider gets off and validates their fare. For the rule matching semantics below, the end time is computed in local time, as determined by [Local Time Semantics](#localtimesemantics) of [timeframes.txt](#timeframestxt). The stop or station of the fare leg’s arrival event should be used for timezone resolution, where appropriate.

For a fare leg rule that specifies a `to_timeframe_group_id`, that rule will match a particular leg if there exists at least one record in `timeframes.txt` where all of the following conditions are true
- The value of `timeframe_group_id` is equal to the `to_timeframe_group_id` value.
- The set of days identified by the record’s `service_id` contains the “current day” of the fare leg’s end time.
- The “time-of-day” of the fare leg's end time is greater than or equal to the record’s `timeframes.start_time` value and less than the `timeframes.end_time` value.

An empty `fare_leg_rules.to_timeframe_group_id` indicates that the end time of the leg does not affect the matching of this rule. | | `fare_product_id` | Foreign ID referencing `fare_products.fare_product_id` | **Required** | The fare product required to travel the leg. | ### fare_transfer_rules.txt @@ -489,7 +519,7 @@ Shapes describe the path that a vehicle travels along a route alignment, and are | `shape_pt_lat` | Latitude | **Required** | Latitude of a shape point. Each record in [shapes.txt](#shapestxt) represents a shape point used to define the shape. | | `shape_pt_lon` | Longitude | **Required** | Longitude of a shape point. | | `shape_pt_sequence` | Non-negative integer | **Required** | Sequence in which the shape points connect to form the shape. Values must increase along the trip but do not need to be consecutive.
*Example: If the shape "A_shp" has three points in its definition, the [shapes.txt](#shapestxt) file might contain these records to define the shape:*
`shape_id,shape_pt_lat,shape_pt_lon,shape_pt_sequence`
`A_shp,37.61956,-122.48161,0`
`A_shp,37.64430,-122.41070,6`
`A_shp,37.65863,-122.30839,11` | -| `shape_dist_traveled` | Non-negative float | Optional | Actual distance traveled along the shape from the first shape point to the point specified in this record. Used by trip planners to show the correct portion of the shape on a map. Values must increase along with `shape_pt_sequence`; they must not be used to show reverse travel along a route. Distance units must be consistent with those used in [stop_times.txt](#stop_timestxt).
*Example: If a bus travels along the three points defined above for A_shp, the additional `shape_dist_traveled` values (shown here in kilometers) would look like this:*
`shape_id,shape_pt_lat,shape_pt_lon,shape_pt_sequence,shape_dist_traveled`
`A_shp,37.61956,-122.48161,0,0`
`A_shp,37.64430,-122.41070,6,6.8310`
`A_shp,37.65863,-122.30839,11,15.8765` | +| `shape_dist_traveled` | Non-negative float | Optional | Actual distance traveled along the shape from the first shape point to the point specified in this record. Used by trip planners to show the correct portion of the shape on a map. Values must increase along with `shape_pt_sequence`; they must not be used to show reverse travel along a route. Distance units must be consistent with those used in [stop_times.txt](#stop_timestxt).

Recommended for routes that have looping or inlining (the vehicle crosses or travels over the same portion of alignment in one trip).

If a vehicle retraces or crosses the route alignment at points in the course of a trip, `shape_dist_traveled` is important to clarify how portions of the points in `shapes.txt` line up correspond with records in `stop_times.txt`.
*Example: If a bus travels along the three points defined above for A_shp, the additional `shape_dist_traveled` values (shown here in kilometers) would look like this:*
`shape_id,shape_pt_lat,shape_pt_lon,shape_pt_sequence,shape_dist_traveled`
`A_shp,37.61956,-122.48161,0,0`
`A_shp,37.64430,-122.41070,6,6.8310`
`A_shp,37.65863,-122.30839,11,15.8765` | ### frequencies.txt @@ -633,7 +663,7 @@ In regions that have multiple official languages, transit agencies/operators typ ### feed_info.txt -File: **Optional** (**Required** if `translations.txt` is provided) +File: **Recommended** (**Required** if `translations.txt` is provided) Primary key (none) @@ -647,11 +677,11 @@ If both referencing methods (`record_id`, `record_sub_id`) and `field_value` are | `feed_publisher_url` | URL | **Required** | URL of the dataset publishing organization's website. This may be the same as one of the `agency.agency_url` values. | | `feed_lang` | Language code | **Required** | Default language used for the text in this dataset. This setting helps GTFS consumers choose capitalization rules and other language-specific settings for the dataset. The file `translations.txt` can be used if the text needs to be translated into languages other than the default one.

The default language may be multilingual for datasets with the original text in multiple languages. In such cases, the `feed_lang` field should contain the language code `mul` defined by the norm ISO 639-2, and a translation for each language used in the dataset should be provided in `translations.txt`. If all the original text in the dataset is in the same language, then `mul` should not be used.
_Example: Consider a dataset from a multilingual country like Switzerland, with the original `stops.stop_name` field populated with stop names in different languages. Each stop name is written according to the dominant language in that stop’s geographic location, e.g. `Genève` for the French-speaking city of Geneva, `Zürich` for the German-speaking city of Zurich, and `Biel/Bienne` for the bilingual city of Biel/Bienne. The dataset `feed_lang` should be `mul` and translations would be provided in `translations.txt`, in German: `Genf`, `Zürich` and `Biel`; in French: `Genève`, `Zurich` and `Bienne`; in Italian: `Ginevra`, `Zurigo` and `Bienna`; and in English: `Geneva`, `Zurich` and `Biel/Bienne`._ | | `default_lang` | Language code | Optional | Defines the language that should be used when the data consumer doesn’t know the language of the rider. It will often be `en` (English). | -| `feed_start_date` | Date | Optional | The dataset provides complete and reliable schedule information for service in the period from the beginning of the `feed_start_date` day to the end of the `feed_end_date` day. Both days may be left empty if unavailable. The `feed_end_date` date must not precede the `feed_start_date` date if both are given. It is recommended that dataset providers give schedule data outside this period to advise of likely future service, but dataset consumers should treat it mindful of its non-authoritative status. If `feed_start_date` or `feed_end_date` extend beyond the active calendar dates defined in [calendar.txt](#calendartxt) and [calendar_dates.txt](#calendar_datestxt), the dataset is making an explicit assertion that there is no service for dates within the `feed_start_date` or `feed_end_date` range but not included in the active calendar dates. | -| `feed_end_date` | Date | Optional | (see above) | -| `feed_version` | Text | Optional | String that indicates the current version of their GTFS dataset. GTFS-consuming applications can display this value to help dataset publishers determine whether the latest dataset has been incorporated. | -| `feed_contact_email` | Email | Optional | Email address for communication regarding the GTFS dataset and data publishing practices. `feed_contact_email` is a technical contact for GTFS-consuming applications. Provide customer service contact information through [agency.txt](#agencytxt). | -| `feed_contact_url` | URL | Optional | URL for contact information, a web-form, support desk, or other tools for communication regarding the GTFS dataset and data publishing practices. `feed_contact_url` is a technical contact for GTFS-consuming applications. Provide customer service contact information through [agency.txt](#agencytxt). | +| `feed_start_date` | Date | Recommended | The dataset provides complete and reliable schedule information for service in the period from the beginning of the `feed_start_date` day to the end of the `feed_end_date` day. Both days may be left empty if unavailable. The `feed_end_date` date must not precede the `feed_start_date` date if both are given. It is recommended that dataset providers give schedule data outside this period to advise of likely future service, but dataset consumers should treat it mindful of its non-authoritative status. If `feed_start_date` or `feed_end_date` extend beyond the active calendar dates defined in [calendar.txt](#calendartxt) and [calendar_dates.txt](#calendar_datestxt), the dataset is making an explicit assertion that there is no service for dates within the `feed_start_date` or `feed_end_date` range but not included in the active calendar dates. | +| `feed_end_date` | Date | Recommended | (see above) | +| `feed_version` | Text | Recommended | String that indicates the current version of their GTFS dataset. GTFS-consuming applications can display this value to help dataset publishers determine whether the latest dataset has been incorporated. | +| `feed_contact_email` | Email | Optional | Email address for communication regarding the GTFS dataset and data publishing practices. `feed_contact_email` is a technical contact for GTFS-consuming applications. Provide customer service contact information through [agency.txt](#agencytxt). It's recommended that at least one of `feed_contact_email` or `feed_contact_url` are provided. | +| `feed_contact_url` | URL | Optional | URL for contact information, a web-form, support desk, or other tools for communication regarding the GTFS dataset and data publishing practices. `feed_contact_url` is a technical contact for GTFS-consuming applications. Provide customer service contact information through [agency.txt](#agencytxt). It's recommended that at least one of `feed_contact_url` or `feed_contact_email` are provided. | ### attributions.txt