TS-47: Dates and Times
This technical standard sets out some best practices for working with, and storing, date and time values.
Date and time values are captured in string data types in most programming languages and data storage systems. There are multiple formats that can be used to represent date and time values in a string. Which date and time formats to support is an important design consideration. The choice can have impacts on quality attributes of a system, notably interoperability with other systems, but also maintainability and usability.
Applications MUST use the https://www.rfc-editor.org/rfc/rfc3339 standard – which is analogous to the ISO 8601 standard – for representing dates and times in data storage and data exchange formats.
It is strongly RECOMMENDED that applications use a small subset of date and time encoding formats, which are compliant with both RFC 3339 and ISO 8601, and also which have a high degree of interoperability with other standards such as the HTML Living Standard.
The RECOMMENDED subset of date and time formats for use in applications are shown in the table below.
Description | Format | Example |
|---|---|---|
Date only | %Y-%M-%D | 2025-12-31 |
Time in UTC | %h:%m:%sZ | 23:59:59Z |
Time with UTC offset | %h:%m:%s±00:00 | 23:59:59+00:00 |
Date and time in UTC | %Y-%M-%DT%h:%m:%sZ | 2025-12-31T23:59:59Z |
Date and time with UTC offset | %Y-%M-%DT%h:%m:%s±00:00 | 2025-12-31T23:59:59-00:00 |
Notice the use of uppercase T and Z symbols, rather than lowercase.
Split second formats – eg. 2025-01-10T11:15:21.027652567Z – SHOULD be used
only when the fine-grained precision is required for a use case, for example in
high-frequency trading systems, scientific applications, or for performance
benchmarking.
Dates and times SHOULD be transmitted and stored in UTC, and converted to the local time zone only when required for application output or processing. An exception to this rule is when the local time zone is a critical part of the data and it is a requirement that the data be represented in the original time zone.
Applications MAY accept date and time values in a wider range of formats as input, for a more convenient user experience, but alternative formats SHOULD be converted to the recommended subset of formats before persisting the data or exchanging rhe data with other internal systems.
Dates and times SHOULD be rendered in a human-readable locale-specific format for user interfaces.
Timestamps and the Year 2038 problem
A Unix timestamp is a count of seconds since the Unix epoch (1970-01-01T00:00:00Z). Many systems and programming languages historically store timestamps as a signed 32-bit integer. A signed 32-bit integer overflows at 231-1 seconds from the epoch, which corresponds to 2038-01-19T03:14:07Z. At one second past that moment, the value wraps to a negative number, representing a date in 1901. This is the Year 2038 problem (Y2038, or Y2K38).
Use 64-bit timestamps
Applications and data storage systems MUST use timestamp representations that are wide enough to accommodate dates beyond 2038. A signed 64-bit integer counts seconds for hundreds of billions of years and is effectively immune to overflow. Most modern programming languages and databases provide 64-bit timestamp types by default, but this MUST be verified rather than assumed — particularly when interfacing with legacy systems, C libraries, file formats, or binary protocols that use 32-bit timestamps.
Avoid 32-bit timestamp types
The following are common sources of 32-bit timestamp limitations:
- C and C++ —
time_tis 32-bit on some legacy platforms and embedded systems. Use a 64-bit type (int64_tor the platform’s 64-bittime_t) explicitly. - SQL — The
TIMESTAMPtype in some database engines uses 32-bit storage and cannot represent dates beyond 2038. PreferDATETIMEor a 64-bitTIMESTAMPwhere available. See TS-43: Relational Databases and SQL. - Binary formats and protocols — Some file formats and wire protocols reserve 32 bits for timestamps. When designing new formats, use at least 64 bits. When consuming existing formats, check the specification and document the limitation.
Prefer string representations for storage and exchange
The most robust defense against timestamp overflow is to store and exchange dates and times as RFC 3339 strings rather than as integer timestamps. A string representation has no fixed width and is not subject to integer overflow. See the main body of this standard for the RECOMMENDED formats.
Where an integer timestamp is required — for example, in a compact binary protocol — it MUST be at least 64 bits wide.
References
- RFC 3339 vs ISO 8601: A useful venn diagram showing where these two standards overlap.