Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change to OSM opening_hours format for times and dates #328

Merged
merged 10 commits into from
Jan 12, 2022
114 changes: 21 additions & 93 deletions gbfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S
* [station_information.json](#station_informationjson)
* [station_status.json](#station_statusjson)
* [free_bike_status.json](#free_bike_statusjson)
* [system_hours.json](#system_hoursjson)
* [system_calendar.json](#system_calendarjson)
* [system_hours.json](#system_hoursjson) *(deprecated in v3.0)*
* [system_calendar.json](#system_calendarjson) *(deprecated in v3.0)*
* [system_regions.json](#system_regionsjson)
* [system_pricing_plans.json](#system_pricing_plansjson)
* [system_alerts.json](#system_alertsjson)
Expand Down Expand Up @@ -81,8 +81,8 @@ vehicle_types.json <br/>*(added in v2.1)* | Conditionally REQUIRED | Describes t
station_information.json | Conditionally REQUIRED | List of all stations, their capacities and locations. REQUIRED of systems utilizing docks.
station_status.json | Conditionally REQUIRED | Number of available vehicles and docks at each station and station availability. REQUIRED of systems utilizing docks.
free_bike_status.json | Conditionally REQUIRED | *(as of v2.1)* Describes all vehicles that are not currently in active rental. REQUIRED for free floating (dockless) vehicles. OPTIONAL for station based (docked) vehicles. Vehicles that are part of an active rental MUST NOT appear in this feed.
system_hours.json | OPTIONAL | Hours of operation for the system.
system_calendar.json | OPTIONAL | Dates of operation for the system.
system_hours.json | - | This file is deprecated *(as of v3.0)*. See `system_information.opening_hours` for system hours of operation.
system_calendar.json | - | This file is deprecated *(as of v3.0)*. See `system_information.opening_hours` for system dates of operation.
system_regions.json | OPTIONAL | Regions the system is broken up into.
system_pricing_plans.json | OPTIONAL | System pricing scheme.
system_alerts.json | OPTIONAL | Current system alerts.
Expand All @@ -101,9 +101,17 @@ Producers SHOULD provide a technical contact who can respond to feed outages in

### Seasonal Shutdowns, Disruptions of Service

Feeds SHOULD continue to be published during seasonal or temporary shutdowns. Feed URLs SHOULD NOT return a 404. An empty bikes array SHOULD be returned by `free_bike_status.json`. Stations in `station_status.json` SHOULD be set to `is_renting:false`, `is_returning:false` and `is_installed:false` where applicable. Seasonal shutdown dates SHOULD be reflected in `system_calendar.json`.
Feeds SHOULD continue to be published during seasonal or temporary shutdowns. Feed URLs SHOULD NOT return a 404. An empty `bikes` array SHOULD be returned by `free_bike_status.json`. Stations in `station_status.json` SHOULD be set to `is_renting:false`, `is_returning:false` and `is_installed:false` where applicable. Seasonal shutdown dates SHOULD be reflected using `opening_hours` in `system_information.json`.

Announcements for disruptions of service, including disabled stations or temporary closures of stations or systems SHOULD be made in `system_alerts.json`.
### Hours and Dates of Operation
Beginning with v3.0, hours and dates of operation are described using the Open Street Map [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) format. The OSM opening_hours syntax is quite complex, therefore it is RECOMMENDED that publishers validate their opening_hours data to ensure its accuaracy.
* [OSM opening_hours examples](https://wiki.openstreetmap.org/wiki/Key:opening_hours)
* [OSM opening_hours syntax guide](https://wiki.openstreetmap.org/wiki/Key:opening_hours/specification)
* [OSM opening_hours validation tool](https://openingh.openstreetmap.de/evaluation_tool/)
* [OSM opening_hours project and code libraries](https://github.com/opening-hours)

Hours and dates of operation SHOULD be published even in cases where services are continuously available 24/7. During periods when a system or station is outside of opening hours, stations SHOULD be set to `is_renting = false`. During these periods, `station_status.json.num_bikes_available` and `station_status.json.num_docks_available` SHOULD reflect the number of vehicles and docks that would be available if the system or station were open.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, could this clarify how free_bike_status.json should behave wrt. opening hours since that feed doesn't have is_renting field? I.e. if a system is outside of opening hours, would there be no free bikes? Also, in this paragraph stations SHOULD be set to is_returning=false too outside of opening hours.

We're trying to figure out whether we MUST check system_information.opening_hours when ingesting real-time feeds before surfacing bikes (i.e. this is a breaking proposal) or we can continue gating by is_renting=false, is_returning=false and no bikes in free_bike_status.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if a system is outside of opening hours, there would not be any vehicles available for rent, including free floating bikes. This can be added to the system_information.opening_hours definition.

Also, in this paragraph stations SHOULD be set to is_returning=false too outside of opening hours.

Actually this is not the case - systems typically allow you to end a rental and/or return vehicles outside of opening hours.

We're trying to figure out whether we MUST check system_information.opening_hours when ingesting real-time feeds before surfacing bikes (i.e. this is a breaking proposal) or we can continue gating by is_renting=false, is_returning=false and no bikes in free_bike_status.

This one is harder to answer - It seems like for now, you would have to check system_information.opening_hours in the case of free bikes. In station_status , the num_bikes_available and num_docks_available fields give the numbers that would be available if the station were set to allow rentals. There's a long thread on how this came to be in #94 . The reason was so that you could plan a trip or reserve a vehicle at 5:45 when the system opened at 6:00. There's no equivalent to num_bikes_available in free_bike_status but there's also no where that it says there should be no bikes in free_bike_status when rentals aren't allowed, only when there are no bikes on the street. If there are bikes on the street, they could still appear in free_bike_status when opening_hours evaluates to closed, that's no different from the current spec, it's just that the format and location of the hours of operation are different.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. There's also is_disabled field in free_bike_status which says "This field is used to indicate vehicles that are in the field but not available for rental." It sounds like this field should then be set to false outside of opening hours?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if I agree with that. With station based ( docked) vehicles that's not really how it works and I think it should be the same for free floating. The numbers represented by ststion_status.num_bikes_available and num_docks_available are the number of functional bikes/docks that would be available if is_renting = true. Suppose there's a free floating vehicle with a dead battery and you set 'is_disabled= true' when the system is closed. In the above scenario where you're planning a trip at 5:45 for the system that opens at 6:00, it would appear that this vehicle will be available for rent at 6 but it won't be.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a separate PR to improve documentation / meaning of the is_disabled wrt opening hours.


## File Requirements

Expand Down Expand Up @@ -337,6 +345,7 @@ Field Name | REQUIRED | Type | Defines
`system_id` | Yes | ID | This is a globally unique identifier for the vehicle share system. It is up to the publisher of the feed to guarantee uniqueness and MUST be checked against existing `system_id` fields in [systems.csv](https://github.com/NABSA/gbfs/blob/master/systems.csv) to ensure this. This value is intended to remain the same over the life of the system. <br><br>Each distinct system or geographic area in which vehicles are operated SHOULD have its own `system_id`. Systems IDs SHOULD be recognizable as belonging to a particular system as opposed to random strings - for example, `bcycle_austin` or `biketown_pdx`.
`language` | Yes | Language | The language that will be used throughout the rest of the files. It MUST match the value in the [gbfs.json](#gbfsjson) file.
`name` | Yes | String | Name of the system to be displayed to customers.
`opening_hours` | Yes | String | Hours and dates of operation for the system in [OSM opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) format. *(added in v3.0)*
`short_name` | OPTIONAL | String | OPTIONAL abbreviation for a system.
`operator` | OPTIONAL | String | Name of the system operator.
`url` | OPTIONAL | URL | The URL of the vehicle share system.
Expand Down Expand Up @@ -369,6 +378,7 @@ Field Name | REQUIRED | Type | Defines
"phone_number": "1-800-555-1234",
"name": "Example Bike Rental",
"operator": "Example Sharing, Inc",
"opening_hours": "Apr 1 - Nov 3 00:00-24:00",
"start_date": "2010-06-10",
"purchase_url": "https://www.example.com",
"timezone": "US/Central",
Expand Down Expand Up @@ -447,6 +457,7 @@ Field Name | REQUIRED | Type | Defines
\-&nbsp;`region_id` | OPTIONAL | ID | Identifier of the region where station is located. See [system_regions.json](#system_regionsjson).
\-&nbsp;`post_code` | OPTIONAL | String | Postal code where station is located.
\-&nbsp;`rental_methods` | OPTIONAL | Array | Payment methods accepted at this station. <br /> Current valid values are:<br /> <ul><li>`key` (e.g. operator issued vehicle key / fob / card)</li><li>`creditcard`</li><li>`paypass`</li><li>`applepay`</li><li>`androidpay`</li><li>`transitcard`</li><li>`accountnumber`</li><li>`phone`</li></ul>
\-&nbsp;`station_opening_hours` | OPTIONAL | String | Hours of operation for the station in [OSM opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) format. If `station_opening_hours` is defined it overrides any `opening_hours` defined in `system_information.json` for the station for which it is defined.
\-&nbsp;`is_virtual_station` <br/>*(added in v2.1)* | OPTIONAL | Boolean | Is this station a location with or without physical infrastructures (docks)? <br /><br /> `true` - The station is a location without physical infrastructure, defined by a point (lat/lon) and/or `station_area` (below). <br /> `false` - The station consists of physical infrastructure (docks). <br /><br /> If this field is empty, it means the station consists of physical infrastructure (docks).<br><br>This field SHOULD be published in systems that have station locations without standard, internet connected physical docking infrastructure. These may be racks or geofenced areas designated for rental and/or return of vehicles. Locations that fit within this description SHOULD have the `is_virtual_station` boolean set to `true`.
\-&nbsp;`station_area` <br/>*(added in v2.1)* | OPTIONAL | GeoJSON Multipolygon | A GeoJSON multipolygon that describes the area of a virtual station. If `station_area` is supplied then the record describes a virtual station. <br /><br /> If lat/lon and `station_area` are both defined, the lat/lon is the significant coordinate of the station (e.g. dock facility or valet drop-off and pick up point). The `station_area` takes precedence over any `ride_allowed` rules in overlapping `geofencing_zones`.
\-&nbsp;`capacity` | OPTIONAL | Non-negative integer | Number of total docking points installed at this station, both available and unavailable, regardless of what vehicle types are allowed at each dock. <br/><br/>If this is a virtual station defined using the `is_virtual_station` field, this number represents the total number of vehicles of all types that can be parked at the virtual station.<br/><br/>If the virtual station is defined by `station_area`, this is the number that can park within the station area. If `lat`/`lon` are defined, this is the number that can park at those coordinates.
Expand All @@ -458,7 +469,7 @@ Field Name | REQUIRED | Type | Defines
&emsp;\-&nbsp;`ios` <br/>*(added in v1.1)* | OPTIONAL | URI | URI that can be used on iOS to launch the rental app for this station. More information on this iOS feature can be found [here](https://developer.apple.com/documentation/uikit/core_app/allowing_apps_and_websites_to_link_to_your_content/communicating_with_other_apps_using_custom_urls?language=objc). Please use iOS Universal Links (https://developer.apple.com/ios/universal-links/) if possible so viewing apps don’t need to manually manage the redirect of the user to the app store if the user doesn’t have the application installed. <br><br>This URI SHOULD be a deep link specific to this station, and SHOULD NOT be a general rental page that includes information for more than one station. The deep link SHOULD take users directly to this station, without any prompts, interstitial pages, or logins. Make sure that users can see this station even if they never previously opened the application. <br><br>If this field is empty, it means deep linking isn’t supported in the native iOS rental app. <br><br>Note that the URI does not necessarily include the station_id - other identifiers can be used by the rental app within the URL to uniquely identify this station. <br><br>See the [Analytics](#analytics-added-in-v11) section for how viewing apps can report the origin of the deep link to rental apps. <br><br>iOS Universal Links example value: `https://www.example.com/app?sid=1234567890&platform=ios` <br><br>Deep Link (without Universal Links) example value: `com.example.ios://open.example.app/app?sid=1234567890`
&emsp;\-&nbsp;`web` <br/>*(added in v1.1)* | OPTIONAL | URL | URL that can be used by a web browser to show more information about renting a vehicle at this station. <br><br>This URL SHOULD be a deep link specific to this station, and SHOULD NOT be a general rental page that includes information for more than one station. The deep link SHOULD take users directly to this station, without any prompts, interstitial pages, or logins. Make sure that users can see this station even if they never previously opened the application. <br><br>If this field is empty, it means deep linking isn’t supported for web browsers. <br><br>Example value: `https://www.example.com/app?sid=1234567890`

##### Example 1: Physical station
##### Example 1: Physical station with limited hours of operation

```jsonc
{
Expand All @@ -472,6 +483,7 @@ Field Name | REQUIRED | Type | Defines
"name": "Parking garage A",
"lat": 12.345678,
"lon": 45.678901,
"station_opening_hours": "Su-Th 05:00-22:00; Fr-Sa 05:00-01:00",
"vehicle_type_capacity": {
"abc123": 7,
"def456": 9
Expand All @@ -493,7 +505,7 @@ Field Name | REQUIRED | Type | Defines
"stations": [
{
"station_id": "station12",
"name": "SE Belmont & SE 10 th",
"name": "SE Belmont & SE 10th",
"lat": -122.655775,
"lon": 45.516445,
"is_valet_station": false,
Expand Down Expand Up @@ -693,98 +705,14 @@ Field Name | REQUIRED | Type | Defines

### system_hours.json

This OPTIONAL file is used to describe hours and days of operation when vehicles are available for rental. If `system_hours.json` is not published, it indicates that vehicles are available for rental 24 hours a day, 7 days a week.
This file has been deprecated in v3.0. For earlier versions see the version history in the [README](README.md#read-the-spec--version-history).

Field Name | REQUIRED | Type | Defines
---|---|---|---
`rental_hours` | Yes | Array | Array of objects as defined below. The array MUST contain a minimum of one object identifying hours for every day of the week or a maximum of two for each day of the week objects ( one for each user type).
\-&nbsp;`user_types` | Yes | Array | An array of `member` and/or `nonmember` value(s). This indicates that this set of rental hours applies to either members or non-members only.
\-&nbsp;`days` | Yes | Array | An array of abbreviations (first 3 letters) of English names of the days of the week for which this object applies (e.g. `["mon", "tue", "wed", "thu", "fri", "sat, "sun"]`). Rental hours MUST NOT be defined more than once for each day and user type.
\-&nbsp;`start_time` | Yes | Time | Start time for the hours of operation of the system in the time zone indicated in [system_information.json](#system_informationjson).
\-&nbsp;`end_time` | Yes | Time | End time for the hours of operation of the system in the time zone indicated in [system_information.json](#system_informationjson).

##### Example:

```jsonc
{
"last_updated": 1609866247,
"ttl": 86400,
"version": "3.0",
"data": {
"rental_hours": [
{
"user_types": [ "member" ],
"days": [
"sat",
"sun"
],
"start_time": "00:00:00",
"end_time": "23:59:59"
},
{
"user_types": [ "nonmember" ],
"days": [
"sat",
"sun"
],
"start_time": "05:00:00",
"end_time": "23:59:59"
},
{
"user_types": [
"member",
"nonmember"
],
"days": [
"mon",
"tue",
"wed",
"thu",
"fri"
],
"start_time": "00:00:00",
"end_time": "23:59:59"
}
]
}
}
```

### system_calendar.json

Describes the operating calendar for a system. This OPTIONAL file SHOULD be published by systems that operate seasonally or do not offer continuous year-round service.

Field Name | REQUIRED | Type | Defines
---|---|---|---
`calendars` | Yes | Array | Array of objects describing the system operational calendar. A minimum of one calendar object is REQUIRED. If start and end dates are the same every year, then start_year and end_year SHOULD be omitted.
\-&nbsp;`start_month` | Yes | Non-negative Integer | Starting month for the system operations (`1`-`12`).
\-&nbsp;`start_day` | Yes | Non-negative Integer | Starting date for the system operations (`1`-`31`).
\-&nbsp;`start_year` | OPTIONAL | Non-negative Integer | Starting year for the system operations.
\-&nbsp;`end_month` | Yes | Non-negative Integer | Ending month for the system operations (`1`-`12`).
\-&nbsp;`end_day` | Yes | Non-negative Integer | Ending date for the system operations (`1`-`31`).
\-&nbsp;`end_year` | OPTIONAL | Non-negative Integer | Ending year for the system operations.
This file has been deprecated in v3.0. For earlier versions see the version history in the [README](README.md#read-the-spec--version-history).

##### Example:

```jsonc
{
"last_updated": 1604333830,
"ttl": 86400,
"version": "3.0",
"data": {
"calendars": [
{
"start_month": 4,
"start_day": 1,
"start_year": 2020,
"end_month": 11,
"end_day": 5,
"end_year": 2020
}
]
}
}
```

### system_regions.json

Expand Down