Problem Description

OpenLMIS v3 has certain data that stores dates and times (timestamps). There is a question about how that data should be stored in the database, used in the backend, exposed through the API and used by clients (UI). There are two main types of data that would be stored using timestamps:

  1. Dates that represent an instant in time - timezone applies. In this document, these will be referred to as instant dates.
    1. An example here would be the submitted date field of a requisition. This is the specific point in time where the requisition was submitted for authorization/approval.
  2. Dates that represent an instant in time only after appropriate timezone is added - In this document, these will be referred to as business dates.
    1. An example here would be the start date of a program. This is a date that represents when a program was started. It only becomes an instant in time when an appropriate timezone is added (in this case, an implementation's default timezone).

In v2, most dates in the system were not timezone-aware. As a result, assumptions about timezone would be made, usually some system default that would be different in different contexts (database, Java, browser). There could also be confusion about exactly "when" something occurred, without timezone data.

As v3 development is underway, this pattern continues; many fields in the system are not timezone aware, or system defaults are used, which could potentially create issues (database might have one timezone default, while a microservice Java default has another, which could be different from a client's timezone, etc.).

Dates with Timezone Proposal

Persistent Storage

Since we are currently using Postgres as our backend database, Postgres' timestamp with time zone data type should be used for instant dates, and text data type for business dates.

Java backend code

Java 8's ZonedDateTime should be used when dealing with instant dates (and generally be in UTC), and LocalDate should be used when dealing with business dates.

Custom attribute converters should be defined for both to convert between Java and the database. If necessary, these converters should "translate" dates into UTC timezone before persisting.

Translation details:

Note: a ZonedDateTimeAttributeConverter has already been implemented in the Reference Data Service for use. This converts between ZonedDateTime and java.sql.Timestamp. However, the instant date fields that are of type ZonedDateTime will also need a JPA annotation to explicitly define the column as "timestamp with time zone". See https://github.com/OpenLMIS/openlmis-referencedata/blob/master/src/main/java/org/openlmis/referencedata/domain/SupportedProgram.java's startDate field for an example.

API Interface

During serialization (returning dates through the API):

During deserialization (when dates are provided by a client to an API call):

Frontend Client Usage (i.e. AngularJS UI)

Clients using API calls to display timestamps to user

Clients making API calls

Appendix: Survey of Usage

Places where dates and times are being used currently (as of 2016-12-19 / 2016-12-20):