# ScheduledSessions and eventSchedules

## An Introduction to the `SessionSeries` `subEvent`

In each `SessionSeries`, there are two fields that determine when a session can occur:

1. `subEvent[]` containing `ScheduledSession`s, which are normally present for each item and deemed to be authoritative, i.e. the session is **guaranteed to take place** at this time.<br>
2. The `eventSchedule`, which can include a `Schedule` or `PartialSchedule`. These have more general information useful for supplementing the `ScheduledSession`. They are not necessarily deemed to be authoritative, i.e. the session **may take place** at this time.

{% hint style="info" %}
A `SessionSeries` can contain the following data:

* Only a `ScheduledSession` (with or without an `eventSchedule`); or
* Only a `PartialSchedule` (least common).
  {% endhint %}

{% hint style="info" %}
A `ScheduledSession` has information about **exactly when** a session is going to take place.

An `eventSchedule` can be used to supplement the `ScheduledSession`information displayed to the end user.
{% endhint %}

{% hint style="warning" %}
If a `ScheduledSession` is not present, caution should be exercised when presenting `PartialSchedule` information to the end user as it only tells us that a session **might take place** in the future.
{% endhint %}

{% hint style="success" %}
Top tip: if there are `ScheduledSession`s, any information within the `eventSchedule` (if present) can be considered supplemental. Only if there are no `ScheduledSession` should the `PartialSchedule` included in the `eventSchedule` be used to display non-authoritative information about session timings.
{% endhint %}

## `ScheduledSession`s

Generally speaking, most `SessionSeries` in our data will will include, at a minimum, a `ScheduledSession`. These objects will include information about exactly when a session is going to take place. It should be considered to be the source of truth when it comes to a session's scheduling information.

### Example

```javascript
"subEvent":[
   {
      "url":"https://www.thisisanexample.com",
      "type":"ScheduledSession",
      "endDate":"2021-06-07T09:00:00Z",
      "duration":"PT1H",
      "startDate":"2021-06-07T08:00:00Z",
      "identifier":"https://thisisanexample.com/[...]/2021-06-07T08:00:00Z",
      "id":"https://search.imin.co/events-api/v2/scheduled-sessions/https%3A%2F%2Fthisisanexample.com%2F%5B...%5D%2F2021-06-07T08%3A00%3A00"
   }
],
```

### `ScheduledSession`s and `EventSchedule`s

Where an `EventSeries` includes a `ScheduledSession`, you can treat this as authoritative and can, in theory, disregard any other scheduling information, including the `EventSchedule`.

{% hint style="success" %}
You can present `ScheduledSession`s to the end user on the front as authoritative, i.e. they are definitely taking place.
{% endhint %}

&#x20;However, the `EventSchedule` can be used to supplement the information provided to the end user to improve the UX.

## The `eventSchedule`

The items in a `SessionSeries`'s`eventSchedule` array can be either take the form of a `Schedule`or a `PartialSchedule` and this is dictated by the open data we receive from different providers. As a user of our data, the difference isn't incredibly important, but it may interest you nonetheless.

### Why do we have `Schedule`s and `PartialSchedule`s?

#### `Schedule`s

Where an open data provider does not provide `ScheduledSession`s, they might instead provide `Schedule`s from which we at imin can generate `ScheduledSession`s. We do this because they are required to have certain date/time information (see OpenActive's [required properties](https://developer.openactive.io/data-model/types/schedule#required-properties) ). It is because of this that `Schedule`s include information can reasonably be relied upon by the end user.

{% hint style="info" %}
Internally, imin generates `ScheduledSession`s from `Schedule`s where they exist, as well as exceptions and amendments. This means there where there is a `Schedule`in an `EventSeries`, there will always be a `ScheduledSession`.
{% endhint %}

#### `PartialSchedule`s

Some open data providers will have neither a dedicated `ScheduledSession` feed (authoritative information), nor will they provide `Schedule`s information that allows us to generate `ScheduledSession`s. Instead they might provide `PartialSchedule`s, which contains insufficient information for our Platform to generate `ScheduledSession`s. This is because OpenActive only mandates for the inclusion of `@type` (see [required property](https://developer.openactive.io/data-model/types/partialschedule#required-properties)), which means that a `PartialSchedule` generally does not have an `endDate` nor a `repeatCount`.

{% hint style="danger" %}
Internally, imin does not ever generate `ScheduledSession`s from `PartialSchedule`s. This includes in the `ByID` route.
{% endhint %}

{% hint style="info" %}
The presence of a `PartialSchedule` does not automatically mean that there will be no `ScheduledSession`. This is because a provider of open data can include have a dedicated `ScheduledSession` feed and also include `PartialSchedule` information in their `SessionSeries` feed.
{% endhint %}

{% hint style="info" %}
For more information, please refer to the OpenActive Developers pages for [`Schedule`](https://developer.openactive.io/data-model/types/schedule) and [`PartialSchedule`](https://developer.openactive.io/data-model/types/partialschedule).
{% endhint %}

### What do `Schedule`s/`PartialSchedule`s look like in our data?

#### `Schedule`s

```javascript
"eventSchedule":[
   {
      "type":"Schedule",
      "byDay":[
         "schema: Thursday"
      ],
      "endDate": "2021-05-31",
      "endTime":"10:15",
      "duration":"PT1H",
      "startDate": "2021-05-17",
      "startTime":"09:15",
      "repeatFrequency":"P1W",
   }
   {
      "type":"Schedule",
      "byDay": [
         "schema:Monday",
         "schema:Tuesday",
         "schema:Wednesday",
         "schema:Thursday",
         "schema:Friday"
      ],
      "endDate": "2021-05-31",
      "endTime":"19:30",
      "duration":"PT1H",
      "startDate": "2021-05-17",
      "startTime":"18:30",
      "repeatFrequency":"P2W",
   }
],
```

#### `PartialSchedule`s

```javascript
"eventSchedule":[
   {
      "type":"PartialSchedule",
      "byDay":[
         "schema: Thursday"
      ],
      "endTime":"10:15",
      "duration":"PT1H",
      "startTime":"09:15",
      "repeatFrequency":"P1W",
   }
   {
      "type":"PartialSchedule",
      "byDay": [
         "schema:Monday",
         "schema:Tuesday",
         "schema:Wednesday",
         "schema:Thursday",
         "schema:Friday"
      ],
      "endTime":"19:30",
      "duration":"PT1H",
      "startTime":"18:30",
      "repeatFrequency":"P2W",
   }
],
```

### Displaying `Schedule`s and `PartialSchedule`s on the front end

As a rule of thumb, `Schedule`/`PartialSchedule`s information in our APIs should be approached with caution. This is because the information is limited to such an extent that it is only possible to say that a session **might be taking place**, e.g. the instructor might be ill or the session falls on a Bank Holiday.

{% hint style="info" %}
Regardless of the `type` - `Schedule` or `PartialSchedule`- both objects should be treated the same when it comes to displaying on front end: **as a rough guide to future occurrences.**
{% endhint %}

#### Where there is a `ScheduledSession` present

As noted above, the `ScheduledSession` should always be used as the authority when displaying information to the end user as it is **guaranteed** to take place at this time. However, the `Schedule`/`PartialSchedule` does offer helpful information that can supplement the `ScheduledSession` to further inform the user.

![How a ScheduledSession and an eventSchedule can be rendered to help end users](https://809863394-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LJbuIOE-TIcNUDnkUS7%2F-MAVrrXA-WXPzy-NzC4Y%2F-MAW2o9O5tY4N41mg8ew%2Fdrawing.svg?alt=media\&token=46f9aa5b-40f7-4308-8588-10ee40776daf)

{% hint style="info" %}
Displaying the `Schedule`/`PartialSchedule` information can be useful because all future `ScheduledSession`s may not be available to you to present to the end user due to our [2-week API Lookahead Window](https://docs.imin.co/using-the-platform/understanding-responses#2-week-api-lookahead-window).
{% endhint %}

{% hint style="danger" %}
You should not extrapolate based on the information found in the `eventSchedule` and communicate to the end user that a session will definitely take place, e.g. **every Tuesday and Thursday**, as the future `ScheduledSession`s may tell us otherwise.
{% endhint %}

#### Where there is not a `ScheduledSession` present

Where a `ScheduledSession` is not present and instead only a `PartialSchedule`, we recommend using the data included in the `eventSchedule` to render it on the front end and use a pop-over to explain to the end user that **the session information should be referred to, but not relied upon**, with the best course of action being for the end user to contact the session organiser to check it is taking place.

{% hint style="warning" %}
If you are presenting `PartialSchedule` information to the end user and **there is no `ScheduledSession`**, it should be made abundantly clear that:

* **The sessions are not guaranteed to take place;** and<br>
* **They should contact the organiser to find out whether it is taking place or not.**
  {% endhint %}

OpenActive also recommends taking this approach, noting in its [Modelling Specification](https://www.openactive.io/modelling-opportunity-data/#partial-schedules) that consideration should be given to how information pertaining to a `PartialSchedule` is displayed to the end user:

> *Data consumers should consider how to present this information in a way that will make it clear to end users that the event details may be subject to change*.

For more information on displaying information from an `EventSchedule` on a front end, please see our page on UX tips [here](https://docs.imin.co/hints-and-tips/untitled/ux-tips-for-displaying-schedule-information).

## Time Zones For `eventSchedule`s

Because a `Schedule`/`PartialSchedule` can occur over time zone boundaries (e.g. it may occur on the week before clocks go forward and the week after), it cannot have a single time zone designator (e.g. `12:00Z` would refer to 12:00 before the clocks go forward and 13:00 after).

This is why the `scheduleTimezone` field is included, which specifies the [IANA time zone](https://www.iana.org/time-zones).

{% hint style="warning" %}
The `scheduleTimezone` field will not always be included. When it is not, please assume that this field is set to `Europe/London`.
{% endhint %}

To render the correct time in JavaScript, you can use [Moment Timezone](https://momentjs.com/timezone/). For example:

```javascript
> const moment = require('moment-timezone');
> const schedule = { /** with the PartialSchedule defined above */ }
> const datetime = moment.tz(
  `${schedule.startDate} ${schedule.startTime}`,
  'YYYY-MM-DD HH:mm',
  schedule.scheduleTimezone || 'Europe/London');
// Render the time using the appropriate timezone designator
> datetime.format();
'2019-07-01T12:00:00+01:00'
// You can also convert it to UTC if you wish
> moment(datetime).utc().format();
'2019-07-01T11:00:00Z'
```
