Timestamps and Time Zones
Timestamps
All Vital data timestamps are ISO 8601 formatted as follows:
Providers | Time Basis | Pattern |
---|---|---|
abbott_libreview freestyle_libre [1] | Floating Time [2] | YYYY-mm-ddTHH:mm:ss+00:00 The +00:00 TZ specifier should be ignored [3]. |
Everyone else | UTC | YYYY-mm-ddTHH:mm:ss+00:00 Always specified as +00:00 (UTC). |
[1]
freestyle_libre
specific:
Some older teams may see floating time data (Freestyle Libre) without the +00:00
TZ specifier,
as part of an earlier iteration of the feature. Contact Vital support if you wish to disable this
behaviour, or if you intend to adopt the Vital backend SDKs.
[2] Floating time is not affixed to any time zone. This is not the same as time relative to a local time zone, i.e., a known UTC offset or geographical location.
[3] Vital sends timestamps in floating time with +00:00
for OpenAPI 3.x interoperability. OAS 3
requires all timestamps to be RFC 3339, which in turn requires
TZ specifier to be mandatory.
When processing data from Freestyle Libre, you should reinterpret literally the date and time components as local date-time in the desired time zone. Do not convert from UTC/Zulu.
Time Zones
Vital formats time zones in data as a nullable integer offset to UTC:
- A positive offset indicates east of UTC.
- A negative offset indicates west of UTC.
null
indicates the time zone information is absent.
Each provider has their own affinity of time zone information:
Affinity | Time Basis | Time Zone |
---|---|---|
✅ | UTC | The data comes with time zone information. |
User Fallback, or UTC | UTC | We assume the data were captured in the User Fallback Time Zone. We fallback to UTC if the former is not set. |
User Fallback, or Absent | UTC | We assume the data were captured in the User Fallback Time Zone. Mark as no time zone (null ) if the former is not set. |
Inferred, or Absent | UTC | We infer the time zone from the data. Mark as no time zone (null ) if the inferrence fails. |
Absent | UTC | We do not know the exact time zone the recording took place in. Mark as no time zone (null ). |
Floating Time | Floating Time | We do not know the exact time zone the recording took place in. Mark as no time zone (null ). |
Cloud-based Providers
Provider | Activity Summary (Daily) | Session Summary (e.g. Sleep) | Timeseries Sample | Remarks |
---|---|---|---|---|
Freestyle Libre freestyle_libre | N/A | N/A | Floating Time | |
Abbott LibreView abbott_libreview | N/A | N/A | Floating Time | |
Fitbit fitbit | ✅ | ✅ | ✅ | ⚠️ Time Zones |
Garmin garmin | ✅ | ✅ | ✅ | |
Google Fit google_fit | User Fallback, or UTC | User Fallback, or Absent | Absent | |
Oura oura | ✅ | ✅ | ✅ | |
Peloton peloton | N/A | ✅ | N/A | |
Renpho renpho | N/A | ✅ | Absent | |
Strava strava | N/A | ✅ | ✅ | |
Wahoo wahoo | N/A | Absent | N/A | |
Whoop whoop_v2 | ✅ | ✅ | N/A | |
Zwift zwift | N/A | User Fallback, or Absent | N/A | |
Withings withings | ✅ | ✅ | ✅ | |
iHealth ihealth | N/A | ✅ | Absent | |
8Sleep eight_sleep | N/A | ✅ | ✅ | |
Hammerhead hammerhead | N/A | Inferred, or Absent | Inferred, or Absent | |
Dexcom dexcom_v3 | N/A | N/A | ✅ | |
Polar polar | ✅ | ✅ | ✅ | |
Kardia kardia | N/A | N/A | ✅ | |
Omron omron | ✅ | N/A | ✅ |
SDK-based Providers
On-device data often do not capture the time zone at recording time. Vital SDK uses the device’s current time zone as the fallback of closest approximation.
Provider | Activity Summary (Daily) | Session Summary | Timeseries Samples |
---|---|---|---|
Apple HealthKit apple_health_kit | ✅ | ✅ | ✅ |
Android Health Connect health_connect | ✅ | ✅ | ✅ |
Omron omron_ble | N/A | N/A | ✅ |
Contour contour_ble | N/A | N/A | ✅ |
Accu-Chek accuchek_ble | N/A | N/A | ✅ |
Freestyle Libre BLE freestyle_libre_ble | N/A | N/A | ✅ |
Examples
Data point with time zone offset
The data point was recorded on July 7, 2023 at 1:00 PM in UTC-07:00.
Data point with no time zone offset (null
)
The data point was timestamped to Aug 13, 2023 at 8:12 AM in UTC+00:00 (Zulu). We do not know the exact time zone the recording took place in.
Data point in floating time (Abbott Libreview & Freestyle Libre)
This Freestyle Libre data point was recorded on Sep 27, 2023 at 7:48 AM in floating time (whichever time zone the user was in). We do not know the exact time zone the recording took place in.
You can display the date and time components literally to the user, e.g., 2023/09/27 07:48 AM
, as they
are relative to their perception of local time.
If you need to convert it to UTC for persistence, you need to pick a time zone based on your understanding of the user. Then you should reinterpret the date and time components literally in said time zone.
For example, we knew that this example user is based in America/New_York
. So we would interpret this data
point to be in 2023/09/27 07:48 AM ET
. We then finally convert this to UTC, resulting in 2023/09/27 11:48 AM UTC
.
User Fallback Time Zone
Some providers neither expose nor even capture time zone information at source. So Vital can only request data and interpret them strictly in UTC.
If you prefer the data to be contextualize to the geographical location of a user, a Fallback Time Zone (denoted by an IANA tz database identifier) can be specified on a per-user basis. Once specified, Vital would use the time zone to pull data and interpret timestamps from any time zone unware providers from that point onwards.
You can specify the Fallback Time Zone when:
You will also get information about the source (by slug) and the last updated time of the Fallback Time Zone when getting an existing user. Fallback Time Zone manually supplied via the REST API would always have a source slug of manual
.