Skip FOLIO Project Navigation

This document describes the general principles regarding how FOLIO operates with international date and time values.

FOLIO uses RFC 3339 as the standard to represent date and time format (i.e. a profile of ISO 8601).

To support tenants that have locations and users in different time zones, FOLIO plans to support user-level time zone setting.

Back-end APIs

Dates and times are stored with the back-end modules as UTC. The APIs assume UTC on input, and store and return timestamps in UTC.

Front-end

The Stripes i18n document explains how they are formatted for display by front-end modules. When comparing or manipulating dates, it is safest to operate in UTC mode and leave display formatting to internationalization helpers.

*.raml and schema.json

With datetime properties in the JSON Schemas, use the type “string” and format “date-time”. For example:

"startDate": {
  "type": "string",
  "format": "date-time",
  "description": "Start date example"
}

and a corresponding JSON sample fragment:

  "startDate": "2018-06-01T11:12:00Z",
  "endDate": "2019-01-01T11:12:00.6+00:00",

With datetime query parameters in RAML 1.0 types, use the type “datetime” or “date-only”. For example:

startDate:
  type: datetime
  example: 2018-11-25T22:00:00.0+00:00

endDate:
  type: datetime
  example: 2018-11-26T16:17:18Z

requestedDate:
  type: date-only
  example: 2018-11-20

Note: The RAML types “datetime” and “date-only” are used with RAML 1.0 only.

Tenant time zone configuration

To respect the tenant chosen timezone on the back-end, use direct call to mod-configuration. FOLIO uses the tz database to specify timezone for a tenant. Default value is “UTC”. Example: America/New_York

SQL

Getting a datetime field as a timestamp without timezone returns it in UTC (time zone +00) irrespective of the SQL client session time zone setting:

SET TIME ZONE '-08';
SELECT creation_date::timestamp,
       (jsonb->'metadata'->>'createdDate')::timestamp,
       (jsonb->'metadata'->>'updatedDate')::timestamp
FROM diku_mod_inventory_storage.instance;
      creation_date      |        timestamp        |        timestamp
-------------------------+-------------------------+-------------------------
 2019-02-23 08:30:57.349 | 2019-02-23 08:30:57.349 | 2019-02-23 08:30:57.349

SET TIME ZONE '+01';
SELECT creation_date::timestamp,
       (jsonb->'metadata'->>'createdDate')::timestamp,
       (jsonb->'metadata'->>'updatedDate')::timestamp
FROM diku_mod_inventory_storage.instance;
      creation_date      |        timestamp        |        timestamp
-------------------------+-------------------------+-------------------------
 2019-02-23 08:30:57.349 | 2019-02-23 08:30:57.349 | 2019-02-23 08:30:57.349

Use the UTC +00 time zone offset to convert the timestamp without timezone into a timestamp with timezone. The result will be in the time zone of the SQL client session:

SET TIME ZONE '-08';
SELECT creation_date::timestamp AT TIME ZONE '+00',
       (jsonb->'metadata'->>'createdDate')::timestamp AT TIME ZONE '+00',
       (jsonb->'metadata'->>'updatedDate')::timestamp AT TIME ZONE '+00'
FROM diku_mod_inventory_storage.instance;
          timezone          |          timezone          |          timezone
----------------------------+----------------------------+----------------------------
 2019-02-23 00:30:57.349-08 | 2019-02-23 00:30:57.349-08 | 2019-02-23 00:30:57.349-08

SET TIME ZONE '+01';
SELECT creation_date::timestamp AT TIME ZONE '+00',
       (jsonb->'metadata'->>'createdDate')::timestamp AT TIME ZONE '+00',
       (jsonb->'metadata'->>'updatedDate')::timestamp AT TIME ZONE '+00'
FROM diku_mod_inventory_storage.instance;
          timezone          |          timezone          |          timezone
----------------------------+----------------------------+----------------------------
 2019-02-23 09:30:57.349+01 | 2019-02-23 09:30:57.349+01 | 2019-02-23 09:30:57.349+01

PostgreSQL documentation: Time Zones, AT TIME ZONE