Problem Description
OpenLMIS v3 has certain data that stores dates (and times). 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 dates (and times):
- Dates that represent an instant in time - timezone applies. In this document, these will be referred to as instant dates.
- An example here would be the created date field of a requisition. This is the specific point in time where the requisition was created and stored.
- Dates that do not represent an instant in time - timezone does not apply. In this document, these will be referred to as general dates.
- An example here would be the expiration date of a drug. This is a date, but it represents when this drug generally expires.
In v2, most dates in the system were not timezone-aware. As a result, the system is not able to support a country/region with multiple timezones. 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 date data type for general dates.
Java backend code
Java 8's ZonedDateTime should be used when dealing with instant dates, and LocalDate when dealing with general dates. Custom attribute converters should be defined to convert between Java and the database.
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
When exposing dates through the API, they should be serialized into a String first. This is because when Jackson serializes date classes, it turns it into an array of values. The serialized String should be in an ISO-8601 format.
Survey of Usage
Places where dates and times are being used currently (as of 2016-12-19 / 2016-12-20):
...