From 94d15cb8410463db30c8a20d63ab1d045b4c33cc Mon Sep 17 00:00:00 2001
From: omar-kabbani <78552622+omar-kabbani@users.noreply.github.com>
Date: Thu, 4 Aug 2022 19:20:43 -0400
Subject: [PATCH 1/2] Added timeframes
---
gtfs/spec/en/reference.md | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md
index b3c39ec39..b7e08a3dd 100644
--- a/gtfs/spec/en/reference.md
+++ b/gtfs/spec/en/reference.md
@@ -17,6 +17,7 @@ This document defines the format and structure of the files that comprise a GTFS
- [stop\_times.txt](#stop_timestxt)
- [calendar.txt](#calendartxt)
- [calendar\_dates.txt](#calendar_datestxt)
+ - [timeframes.txt](#timeframestxt)
- [fare\_attributes.txt](#fare_attributestxt)
- [fare\_rules.txt](#fare_rulestxt)
- [fare\_products.txt](#fare_productstxt)
@@ -300,6 +301,18 @@ The [calendar_dates.txt](#calendar_datestxt) table explicitly activates or disab
| `date` | Date | **Required** | Date when service exception occurs. |
| `exception_type` | Enum | **Required** | Indicates whether service is available on the date specified in the date field. Valid options are:
`1` - Service has been added for the specified date.
`2` - Service has been removed for the specified date.
*Example: Suppose a route has one set of trips available on holidays and another set of trips available on all other days. One `service_id` could correspond to the regular service schedule and another `service_id` could correspond to the holiday schedule. For a particular holiday, the [calendar_dates.txt](#calendar_datestxt) file could be used to add the holiday to the holiday `service_id` and to remove the holiday from the regular `service_id` schedule.* |
+### timeframes.txt
+
+File: **Optional**
+
+Primary key (`timeframe_id`, `start_time`, `end_time`)
+
+| Field Name | Type | Presence | Description |
+| ------ | ------ | ------ | ------ |
+| `timeframe_id` | ID | **Required** | Identifies a timeframe or set of timeframes. |
+| `start_time` | Time | **Required** | Defines the beginning of a timeframe. |
+| `end_time` | Time | **Required** | Defines the end of a timeframe. |
+
### fare_attributes.txt
File: **Optional**
@@ -362,7 +375,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_id, to_timeframe_id, fare_product_id`)
Fare rules for individual legs of travel.
@@ -373,14 +386,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_id`
+ - `fare_leg_rules.to_timeframe_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:
+3. If no exact matches are found, then empty entries in `fare_leg_rules.network_id`, `fare_leg_rules.from_area_id`, `fare_leg_rules.to_area_id`, `fare_leg_rules.from_timeframe_id`, and `fare_leg_rules.to_timeframe_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`
+ - An empty entry in `fare_leg_rules.from_timeframe_id` corresponds to all timeframes defined in `timeframes.timeframe_id` excluding the ones listed under `fare_leg_rules.from_timeframe_id`
+ - An empty entry in `fare_leg_rules.to_timeframe_id` corresponds to all timeframes defined in `timeframes.timeframe_id` excluding the ones listed under `fare_leg_rules.to_timeframe_id`
4. If the leg does not match any of the rules described above, then the fare is unknown.
@@ -393,6 +410,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_id` | Foreign ID referencing `timeframes.timeframe_id` | Optional | Defines a departure timeframe for the fare leg rule.
If there are no matching `fare_leg_rules.from_timeframe_id` values to the `timeframe_id` being filtered, empty `fare_leg_rules.from_timeframe_id` will be matched by default.
An empty entry in `fare_leg_rules.from_timeframe_id` corresponds to all timeframes defined in `timeframes.timeframe_id` excluding the ones listed under `fare_leg_rules.from_timeframe_id` |
+| `to_timeframe_id` | Foreign ID referencing `timeframes.timeframe_id` | Optional | Defines an arrival timeframe for the fare leg rule.
If there are no matching `fare_leg_rules.to_timeframe_id` values to the `timeframe_id` being filtered, empty `fare_leg_rules.to_timeframe_id` will be matched by default.
An empty entry in `fare_leg_rules.to_timeframe_id` corresponds to all timeframes defined in `timeframes.timeframe_id` excluding the ones listed under `fare_leg_rules.to_timeframe_id` |
| `fare_product_id` | Foreign ID referencing `fare_products.fare_product_id` | **Required** | The fare product required to travel the leg. |
### fare_transfer_rules.txt
From bfc2b1224bf7b01cad83d36f3e8f709c199bdd60 Mon Sep 17 00:00:00 2001
From: omar-kabbani <78552622+omar-kabbani@users.noreply.github.com>
Date: Fri, 5 Aug 2022 13:08:35 -0400
Subject: [PATCH 2/2] Add date-based fares
---
gtfs/spec/en/reference.md | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/gtfs/spec/en/reference.md b/gtfs/spec/en/reference.md
index b7e08a3dd..4c34e8103 100644
--- a/gtfs/spec/en/reference.md
+++ b/gtfs/spec/en/reference.md
@@ -108,6 +108,7 @@ This specification defines the following files:
| [stop_times.txt](#stop_timestxt) | **Required** | Times that a vehicle arrives at and departs from stops for each trip. |
| [calendar.txt](#calendartxt) | **Conditionally Required** | Service dates specified using a weekly schedule with start and end dates.
Conditionally Required:
- **Required** unless all dates of service are defined in [calendar_dates.txt](#calendar_datestxt).
- Optional otherwise. |
| [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. |
+| [timeframes.txt](#timeframestxt) | Optional | Service times specified using a 24-hour format with start and end times. |
| [fare_attributes.txt](#fare_attributestxt) | Optional | Fare information for a transit agency's routes. |
| [fare_rules.txt](#fare_rulestxt) | **Conditionally Required** | Rules to apply fares for itineraries.
Conditionally Required:
- **Required** if [fare_attributes.txt](#fare_attributestxt) is defined.
- **Forbidden** otherwise. |
| [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). |
@@ -375,7 +376,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, from_timeframe_id, to_timeframe_id, fare_product_id`)
+Primary Key (`network_id, from_area_id, to_area_id, from_timeframe_id, to_timeframe_id, service_id, fare_product_id`)
Fare rules for individual legs of travel.
@@ -388,16 +389,18 @@ To process the cost of a leg:
- `fare_leg_rules.from_area_id`
- `fare_leg_rules.to_area_id`
- `fare_leg_rules.from_timeframe_id`
- - `fare_leg_rules.to_timeframe_id`
+ - `fare_leg_rules.to_timeframe_id`
+ - `fare_leg_rules.service_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`, `fare_leg_rules.to_area_id`, `fare_leg_rules.from_timeframe_id`, and `fare_leg_rules.to_timeframe_id` must be checked to process 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`, `fare_leg_rules.to_area_id`, `fare_leg_rules.from_timeframe_id`, `fare_leg_rules.to_timeframe_id`, and `fare_leg_rules.service_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.from_timeframe_id` corresponds to all timeframes defined in `timeframes.timeframe_id` excluding the ones listed under `fare_leg_rules.from_timeframe_id`
- - An empty entry in `fare_leg_rules.to_timeframe_id` corresponds to all timeframes defined in `timeframes.timeframe_id` excluding the ones listed under `fare_leg_rules.to_timeframe_id`
+ - An empty entry in `fare_leg_rules.to_timeframe_id` corresponds to all timeframes defined in `timeframes.timeframe_id` excluding the ones listed under `fare_leg_rules.to_timeframe_id`
+ - An empty entry in `fare_leg_rules.service_id` corresponds to all dates defined in `calendar.service_id` excluding the ones listed under `fare_leg_rules.service_id`
4. If the leg does not match any of the rules described above, then the fare is unknown.
@@ -412,6 +415,7 @@ To process the cost of a leg:
| `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_id` | Foreign ID referencing `timeframes.timeframe_id` | Optional | Defines a departure timeframe for the fare leg rule.
If there are no matching `fare_leg_rules.from_timeframe_id` values to the `timeframe_id` being filtered, empty `fare_leg_rules.from_timeframe_id` will be matched by default.
An empty entry in `fare_leg_rules.from_timeframe_id` corresponds to all timeframes defined in `timeframes.timeframe_id` excluding the ones listed under `fare_leg_rules.from_timeframe_id` |
| `to_timeframe_id` | Foreign ID referencing `timeframes.timeframe_id` | Optional | Defines an arrival timeframe for the fare leg rule.
If there are no matching `fare_leg_rules.to_timeframe_id` values to the `timeframe_id` being filtered, empty `fare_leg_rules.to_timeframe_id` will be matched by default.
An empty entry in `fare_leg_rules.to_timeframe_id` corresponds to all timeframes defined in `timeframes.timeframe_id` excluding the ones listed under `fare_leg_rules.to_timeframe_id` |
+| `service_id` | Foreign ID referencing `calendar.service_id` | Optional | Identifies a set of dates that a fare leg rule is in effect.
If there are no matching `fare_leg_rules.service_id` values to the `service_id` being filtered, empty `fare_leg_rules.service_id` will be matched by default.
An empty entry in `fare_leg_rules.service_id` corresponds to all dates defined in `calendar.service_id` excluding the ones listed under `fare_leg_rules.service_id` |
| `fare_product_id` | Foreign ID referencing `fare_products.fare_product_id` | **Required** | The fare product required to travel the leg. |
### fare_transfer_rules.txt