From f12a0ed9c8ebe1a3ad141d737d32f799fcbe3d0a Mon Sep 17 00:00:00 2001 From: Brian Ferris Date: Mon, 15 Jul 2024 00:51:56 -0700 Subject: [PATCH 01/11] GTFS Fares v2: Area Set matching predicates. --- gtfs/spec/en/reference.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 6a6eca8f..918077d6 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -27,6 +27,7 @@ This document defines the format and structure of the files that comprise a GTFS - [fare\_transfer\_rules.txt](#fare_transfer_rulestxt) - [areas.txt](#areastxt) - [stop_areas.txt](#stop_areastxt) + - [area_sets.txt](#areasetstxt) - [networks.txt](#networkstxt) - [route_networks.txt](#route_networkstxt) - [shapes.txt](#shapestxt) @@ -126,6 +127,7 @@ This specification defines the following files: | [fare_transfer_rules.txt](#fare_transfer_rulestxt) | Optional | Fare rules for transfers between legs of travel.

Along with [fare_leg_rules.txt](#fare_leg_rulestxt), file [fare_transfer_rules.txt](#fare_transfer_rulestxt) provides a more detailed method for modeling fare structures. As such, the use of [fare_transfer_rules.txt](#fare_transfer_rulestxt) is entirely separate from files [fare_attributes.txt](#fare_attributestxt) and [fare_rules.txt](#fare_rulestxt). | | [areas.txt](#areastxt) | Optional | Area grouping of locations. | | [stop_areas.txt](#stop_areastxt) | Optional | Rules to assign stops to areas. | +| [area_sets.txt](#areasetstxt) | Optional | Collections of areas. | | [networks.txt](#networkstxt) | **Conditionally Forbidden** | Network grouping of routes.

Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routestxt).
- Optional otherwise. | | [route_networks.txt](#route_networkstxt) | **Conditionally Forbidden** | Rules to assign routes to networks.

Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routestxt).
- Optional otherwise. | | [shapes.txt](#shapestxt) | Optional | Rules for mapping vehicle travel paths, sometimes referred to as route alignments. | @@ -477,12 +479,16 @@ To process the cost of a leg:
+For area set predicates in `fare_leg_rules.txt` specified below, a leg “travels through an area” if any of the stops or parent stations (if the area is not defined at the stop-level) of the leg; including departure, arrival, and intermediate stops; belongs to the specified area as defined by [stop_areas.txt](#stopareastxt). + | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | | `leg_group_id` | ID | Optional | Identifies a group of entries in [fare_leg_rules.txt](#fare_leg_rulestxt).

Used to describe fare transfer rules between `fare_transfer_rules.from_leg_group_id` and `fare_transfer_rules.to_leg_group_id`.

Multiple entries in [fare_leg_rules.txt](#fare_leg_rulestxt) may belong to the same `fare_leg_rules.leg_group_id`.

The same entry in [fare_leg_rules.txt](#fare_leg_rulestxt) (not including `fare_leg_rules.leg_group_id`) must not belong to multiple `fare_leg_rules.leg_group_id`.| | `network_id` | Foreign ID referencing `routes.network_id` or `networks.network_id`| Optional | Identifies a route network that applies for the fare leg rule.

If the `rule_priority` field does not exist AND 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](#routestxt) or [networks.txt](#networkstxt) excluding the ones listed under `fare_leg_rules.network_id`

If the `rule_priority` field exists in the file, an empty `fare_leg_rules.network_id` indicates that the route network of the leg does not affect the matching of this rule. | | `from_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies a departure area.

If the `rule_priority` field does not exist AND 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`

If the `rule_priority` field exists in the file, an empty `fare_leg_rules.from_area_id` indicates that the departure area of the leg does not affect the matching of this rule. | | `to_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies an arrival area.

If the `rule_priority` field does not exist AND 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`

If the `rule_priority` field exists in the file, an empty `fare_leg_rules.to_area_id` indicates that the arrival area of the leg does not affect the matching of this rule. | +| `contains_area_set_id` | Foreign ID referencing `area_sets.area_set_id` | Optional | Identifies an area set containing a collection of areas.

For this rule to match, a leg must travel through each and every area of the area set. The leg may travel through additional areas not contained by the area set or through stops that are not assigned to an area at all. If not specified, this predicate does not affect the matching of this rule. | +| `contains_exactly_area_set_id` | Foreign ID referencing `area_sets.area_set_id` | Optional | Identifies an area set containing a collection of areas.

For this rule to match, a leg must travel through each and every area of the specified area set. Each and every stop the leg travels through must belong to at least one area in the area set. If not specified, this predicate does not affect the matching of this rule. | | `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](#timeframestxt) 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](#timeframestxt) 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. | @@ -550,6 +556,19 @@ Assigns stops from [stops.txt](#stopstxt) to areas. | `area_id` | Foreign ID referencing `areas.area_id` | **Required** | Identifies an area to which one or multiple `stop_id`s belong. The same `stop_id` may be defined in many `area_id`s. | | `stop_id` | Foreign ID referencing `stops.stop_id` | **Required** | Identifies a stop. If a station (i.e. a stop with `stops.location_type=1`) is defined in this field, it is assumed that all of its platforms (i.e. all stops with `stops.location_type=0` that have this station defined as `stops.parent_station`) are part of the same area. This behavior can be overridden by assigning platforms to other areas. | +### area_sets.txt + +File: **Optional** + +Primary key (`*`) + +Groups collections of areas into sets. + +| Field Name | Type | Presence | Description | +| ------ | ------ | ------ | ------ | +| `area_set_id` | Unique ID | **Required** | Identifies an area set. Must be unique in [area_sets.txt](#areasetstxt). | +| `area_id` | Foreign ID referencing `areas.area_id` | **Required** | Identifies an area to be included in the set. The same `area_id` may be defined in multiple area sets. | + ### networks.txt File: **Conditionally Forbidden** From 9bb18739b5f330944e1cfc6473526de5198e8a28 Mon Sep 17 00:00:00 2001 From: Brian Ferris Date: Wed, 24 Jul 2024 11:20:13 -0700 Subject: [PATCH 02/11] Fix #area_setstxt references and add clarifying language about intermediate stops. --- gtfs/spec/en/reference.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 918077d6..fd597c10 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -27,7 +27,7 @@ This document defines the format and structure of the files that comprise a GTFS - [fare\_transfer\_rules.txt](#fare_transfer_rulestxt) - [areas.txt](#areastxt) - [stop_areas.txt](#stop_areastxt) - - [area_sets.txt](#areasetstxt) + - [area_sets.txt](#area_setstxt) - [networks.txt](#networkstxt) - [route_networks.txt](#route_networkstxt) - [shapes.txt](#shapestxt) @@ -127,7 +127,7 @@ This specification defines the following files: | [fare_transfer_rules.txt](#fare_transfer_rulestxt) | Optional | Fare rules for transfers between legs of travel.

Along with [fare_leg_rules.txt](#fare_leg_rulestxt), file [fare_transfer_rules.txt](#fare_transfer_rulestxt) provides a more detailed method for modeling fare structures. As such, the use of [fare_transfer_rules.txt](#fare_transfer_rulestxt) is entirely separate from files [fare_attributes.txt](#fare_attributestxt) and [fare_rules.txt](#fare_rulestxt). | | [areas.txt](#areastxt) | Optional | Area grouping of locations. | | [stop_areas.txt](#stop_areastxt) | Optional | Rules to assign stops to areas. | -| [area_sets.txt](#areasetstxt) | Optional | Collections of areas. | +| [area_sets.txt](#area_setstxt) | Optional | Collections of areas. | | [networks.txt](#networkstxt) | **Conditionally Forbidden** | Network grouping of routes.

Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routestxt).
- Optional otherwise. | | [route_networks.txt](#route_networkstxt) | **Conditionally Forbidden** | Rules to assign routes to networks.

Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routestxt).
- Optional otherwise. | | [shapes.txt](#shapestxt) | Optional | Rules for mapping vehicle travel paths, sometimes referred to as route alignments. | @@ -479,7 +479,7 @@ To process the cost of a leg:
-For area set predicates in `fare_leg_rules.txt` specified below, a leg “travels through an area” if any of the stops or parent stations (if the area is not defined at the stop-level) of the leg; including departure, arrival, and intermediate stops; belongs to the specified area as defined by [stop_areas.txt](#stopareastxt). +For area set predicates in `fare_leg_rules.txt` specified below, a leg “travels through an area” if any of the stops or parent stations (if the area is not defined at the stop-level) of the leg; including departure, arrival, and intermediate stops as referenced by the trip's stop-time entries; belongs to the specified area as defined by [stop_areas.txt](#stopareastxt). | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | @@ -566,7 +566,7 @@ Groups collections of areas into sets. | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | -| `area_set_id` | Unique ID | **Required** | Identifies an area set. Must be unique in [area_sets.txt](#areasetstxt). | +| `area_set_id` | Unique ID | **Required** | Identifies an area set. Must be unique in [area_sets.txt](#area_setstxt). | | `area_id` | Foreign ID referencing `areas.area_id` | **Required** | Identifies an area to be included in the set. The same `area_id` may be defined in multiple area sets. | ### networks.txt From 030d7a727c28408707b675a16113327fc3742082 Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Thu, 7 May 2026 09:22:34 -0400 Subject: [PATCH 03/11] Update gtfs/spec/en/reference.md --- gtfs/spec/en/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index fd597c10..c2ee1123 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -567,7 +567,7 @@ Groups collections of areas into sets. | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | | `area_set_id` | Unique ID | **Required** | Identifies an area set. Must be unique in [area_sets.txt](#area_setstxt). | -| `area_id` | Foreign ID referencing `areas.area_id` | **Required** | Identifies an area to be included in the set. The same `area_id` may be defined in multiple area sets. | +| `area_set_name` | Text | **Optional** | The name of the area set. | ### networks.txt From 8f6608e0c9ab5e89b436dc0bde9e34590593594c Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Thu, 7 May 2026 09:22:53 -0400 Subject: [PATCH 04/11] Update gtfs/spec/en/reference.md --- gtfs/spec/en/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index c2ee1123..95b90055 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -560,7 +560,7 @@ Assigns stops from [stops.txt](#stopstxt) to areas. File: **Optional** -Primary key (`*`) +Primary key (`area_set_id`) Groups collections of areas into sets. From 1ea855ff49df3f792f11d15679754f441eb9e87f Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Thu, 7 May 2026 09:23:21 -0400 Subject: [PATCH 05/11] Update gtfs/spec/en/reference.md --- gtfs/spec/en/reference.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 95b90055..4a15c442 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -568,7 +568,18 @@ Groups collections of areas into sets. | ------ | ------ | ------ | ------ | | `area_set_id` | Unique ID | **Required** | Identifies an area set. Must be unique in [area_sets.txt](#area_setstxt). | | `area_set_name` | Text | **Optional** | The name of the area set. | +### area_set_elements.txt +File: **Optional** + +Primary key (`*`) + +Groups collections of areas into sets. + +| Field Name | Type | Presence | Description | +| ------ | ------ | ------ | ------ | +| `area_set_id` | Foreign ID referencing `area_sets.area_set_id` | **Required** | Identifies an area set to which one or multiple `area_id`s belong. | +| `area_id` | Foreign ID referencing `areas.area_id` | **Required** | Identifies an area to be included in the set. The same `area_id` may be defined in multiple area sets. | ### networks.txt File: **Conditionally Forbidden** From 7091fc81f47e1b58a335f4f1b80ebc5c508f114e Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Thu, 7 May 2026 09:23:55 -0400 Subject: [PATCH 06/11] Update gtfs/spec/en/reference.md --- gtfs/spec/en/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 4a15c442..0b0a46ed 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -562,7 +562,7 @@ File: **Optional** Primary key (`area_set_id`) -Groups collections of areas into sets. +Defines area set identifiers that apply for fare leg rules. | Field Name | Type | Presence | Description | | ------ | ------ | ------ | ------ | From 6498d50b68c5cb6ab28891c8c0a960dab2164123 Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Thu, 7 May 2026 09:24:09 -0400 Subject: [PATCH 07/11] Update gtfs/spec/en/reference.md --- gtfs/spec/en/reference.md | 1 + 1 file changed, 1 insertion(+) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 0b0a46ed..f85b9c73 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -128,6 +128,7 @@ This specification defines the following files: | [areas.txt](#areastxt) | Optional | Area grouping of locations. | | [stop_areas.txt](#stop_areastxt) | Optional | Rules to assign stops to areas. | | [area_sets.txt](#area_setstxt) | Optional | Collections of areas. | +| [area_set_elements.txt](#area_set_elementstxt) | Optional | Rules to assign areas to area sets. | | [networks.txt](#networkstxt) | **Conditionally Forbidden** | Network grouping of routes.

Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routestxt).
- Optional otherwise. | | [route_networks.txt](#route_networkstxt) | **Conditionally Forbidden** | Rules to assign routes to networks.

Conditionally Forbidden:
- **Forbidden** if `network_id` exists in [routes.txt](#routestxt).
- Optional otherwise. | | [shapes.txt](#shapestxt) | Optional | Rules for mapping vehicle travel paths, sometimes referred to as route alignments. | From 30159908959f28282bcb05353e99743480c8a6fa Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Thu, 7 May 2026 09:24:37 -0400 Subject: [PATCH 08/11] Update gtfs/spec/en/reference.md --- gtfs/spec/en/reference.md | 1 + 1 file changed, 1 insertion(+) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index f85b9c73..edb71644 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -28,6 +28,7 @@ This document defines the format and structure of the files that comprise a GTFS - [areas.txt](#areastxt) - [stop_areas.txt](#stop_areastxt) - [area_sets.txt](#area_setstxt) + - [area_set_elements.txt](#area_set_elementstxt) - [networks.txt](#networkstxt) - [route_networks.txt](#route_networkstxt) - [shapes.txt](#shapestxt) From 1290b56dae958d1923331efce528b74dc610406e Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Thu, 7 May 2026 09:25:08 -0400 Subject: [PATCH 09/11] Update gtfs/spec/en/reference.md --- gtfs/spec/en/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index edb71644..f697b8e1 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -445,7 +445,7 @@ Used to describe the range of fares available for purchase by riders or taken in File: **Optional** -Primary key (`network_id, from_area_id, to_area_id, from_timeframe_group_id, to_timeframe_group_id, fare_product_id`) +Primary key (`network_id, from_area_id, to_area_id, from_timeframe_group_id, to_timeframe_group_id, contains_exactly_area_set_id, contains_area_set_id, fare_product_id`) Fare rules for individual legs of travel. From 0b8817ffa2264ad5a8d4a221dcadcfad3e49eb9a Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Thu, 7 May 2026 09:25:22 -0400 Subject: [PATCH 10/11] Update gtfs/spec/en/reference.md --- gtfs/spec/en/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index f697b8e1..262bba85 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -489,7 +489,7 @@ For area set predicates in `fare_leg_rules.txt` specified below, a leg “travel | `network_id` | Foreign ID referencing `routes.network_id` or `networks.network_id`| Optional | Identifies a route network that applies for the fare leg rule.

If the `rule_priority` field does not exist AND 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](#routestxt) or [networks.txt](#networkstxt) excluding the ones listed under `fare_leg_rules.network_id`

If the `rule_priority` field exists in the file, an empty `fare_leg_rules.network_id` indicates that the route network of the leg does not affect the matching of this rule. | | `from_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies a departure area.

If the `rule_priority` field does not exist AND 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`

If the `rule_priority` field exists in the file, an empty `fare_leg_rules.from_area_id` indicates that the departure area of the leg does not affect the matching of this rule. | | `to_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies an arrival area.

If the `rule_priority` field does not exist AND 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`

If the `rule_priority` field exists in the file, an empty `fare_leg_rules.to_area_id` indicates that the arrival area of the leg does not affect the matching of this rule. | -| `contains_area_set_id` | Foreign ID referencing `area_sets.area_set_id` | Optional | Identifies an area set containing a collection of areas.

For this rule to match, a leg must travel through each and every area of the area set. The leg may travel through additional areas not contained by the area set or through stops that are not assigned to an area at all. If not specified, this predicate does not affect the matching of this rule. | +| `contains_area_set_id` | Foreign ID referencing `area_sets.area_set_id` | Conditionally Forbidden | Identifies an area set containing a collection of areas.

For this rule to match, a leg must travel through each and every area of the area set. The leg may travel through additional areas not contained by the area set or through stops that are not assigned to an area at all. If not specified, this predicate does not affect the matching of this rule.

Conditionally Forbidden:
- **Forbidden** if `contains_exactly_area_set_id` is defined.
- Optional otherwise. | | `contains_exactly_area_set_id` | Foreign ID referencing `area_sets.area_set_id` | Optional | Identifies an area set containing a collection of areas.

For this rule to match, a leg must travel through each and every area of the specified area set. Each and every stop the leg travels through must belong to at least one area in the area set. If not specified, this predicate does not affect the matching of this rule. | | `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](#timeframestxt) 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](#timeframestxt) 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. | From 7d83f093587a5ff30ae883c819244a11ba47f261 Mon Sep 17 00:00:00 2001 From: Tzu-Jen Chan <126435471+tzujenchanmbd@users.noreply.github.com> Date: Thu, 7 May 2026 09:25:38 -0400 Subject: [PATCH 11/11] Update gtfs/spec/en/reference.md --- gtfs/spec/en/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md index 262bba85..51c8f752 100644 --- a/gtfs/spec/en/reference.md +++ b/gtfs/spec/en/reference.md @@ -490,7 +490,7 @@ For area set predicates in `fare_leg_rules.txt` specified below, a leg “travel | `from_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies a departure area.

If the `rule_priority` field does not exist AND 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`

If the `rule_priority` field exists in the file, an empty `fare_leg_rules.from_area_id` indicates that the departure area of the leg does not affect the matching of this rule. | | `to_area_id` | Foreign ID referencing `areas.area_id` | Optional | Identifies an arrival area.

If the `rule_priority` field does not exist AND 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`

If the `rule_priority` field exists in the file, an empty `fare_leg_rules.to_area_id` indicates that the arrival area of the leg does not affect the matching of this rule. | | `contains_area_set_id` | Foreign ID referencing `area_sets.area_set_id` | Conditionally Forbidden | Identifies an area set containing a collection of areas.

For this rule to match, a leg must travel through each and every area of the area set. The leg may travel through additional areas not contained by the area set or through stops that are not assigned to an area at all. If not specified, this predicate does not affect the matching of this rule.

Conditionally Forbidden:
- **Forbidden** if `contains_exactly_area_set_id` is defined.
- Optional otherwise. | -| `contains_exactly_area_set_id` | Foreign ID referencing `area_sets.area_set_id` | Optional | Identifies an area set containing a collection of areas.

For this rule to match, a leg must travel through each and every area of the specified area set. Each and every stop the leg travels through must belong to at least one area in the area set. If not specified, this predicate does not affect the matching of this rule. | +| `contains_exactly_area_set_id` | Foreign ID referencing `area_sets.area_set_id` | Conditionally Forbidden | Identifies an area set containing a collection of areas.

For this rule to match, a leg must travel through each and every area of the specified area set. Each and every stop the leg travels through must belong to at least one area in the area set. If not specified, this predicate does not affect the matching of this rule.

Conditionally Forbidden:
- **Forbidden** if `contains_area_set_id` is defined.
- Optional otherwise. | | `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](#timeframestxt) 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](#timeframestxt) 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. |