Skip to main content

How to Assure Quality in Date-Time Values in Software Development

article
|
User on a laptop computer with Y2038 bug on the screen
Summary

The impending Unix Y2038 bug, caused by 32-bit signed integer limits, poses significant quality assurance challenges for date-time values in software development. Mitigating this risk requires transitioning hardware, operating systems, and application layers to 64-bit architectures to ensure long-term system stability.

To understand why QA is critical for date-time values, we only need to look back to 1999; despite advanced database technology, the Y2K bug still occurred. When database software developers first developed programs, they must not have been anticipative enough. The Y2K issue would not have happened if the year field in a date were stored only as a complete value; for example, ‘1970’, instead of ‘70’. Thereafter, the British Standards Institution committee laid out the rules for Year 2000 conformity.

However, software developers still need to be aware of similar potential issues that could occur in the future related to date-time values.

Using Four or Two Digits to Store a Year Value

Ideally, specify a Year value as a four-digit number. However, if one still prefers two-digit values, some databases such as MySQL, and Oracle, do support it. However, note that the logic used by MySQL and Oracle for storing 2-digit year values involves guesswork. Therefore, if 2-digit year values must be encoded, it is recommended to perform a code review periodically to ensure that values are stored as designed. This is because how databases guess the year is likely to change. Admittedly, it wouldn’t be prudent to store ‘70’ as ‘1970’ in 2070, as databases store today! That is why it is recommended to specify the year as a four-digit value, always.

A Three-Tiered Approach to Y2038 Mitigation (Hardware, OS, and Application Layer)

First, let’s introduce what the Unix time Y2038 bug is.

A date and time best practice that developers need to be aware of in computing is to not use Unix time for storing date-time data. The Unix time system measures time in non-leap seconds, starting at 00:00:00 UTC on 1 January 1970, the Unix epoch. It stores value as a signed 32-bit integer. Anyone familiar with binary math can calculate that the maximum value a signed 32-bit integer can hold is represented by 01111111 11111111 11111111 11111111, which implies that a computer system using Unix time can't represent a date value after 03:14:07 UTC on 19 January 2038.

Hardware

As a general recommendation, use 64-bit hardware architecture. Hardware support can be verified with the lscpu command. The command output should be similar to the following:

lscpu
Architecture:       x86_64

Use embedded systems that use the 64-bit hardware architecture and use 64-bit date-time based software. A clock in routine use showing an incorrect time when the year 2038 rolls over is not a cause for concern, because it is similar to having to set a clock forward/backward at Spring daylight saving start/end, if a clock is not set automatically. However, it is a critical issue in some embedded systems. While it is relatively easier to update software in larger computer systems, embedded systems are generally not designed for updates. This means that older 32-bit based embedded systems will fail after the aforementioned date - 03:14:07 UTC on 19 January 2038.

As an example, Automatic Four-Wheel Drive systems, especially older models that store delta-time values commonly used for detecting skids and managing traction as signed 32-bit integers, are susceptible to the Y2038 bug. As the Y2038 bug date rolls over, an embedded system like the one used in an automatic four-wheel drive will get into a rollover stuck state, referring to the state after time rolls over the supported timestamp range. Therefore, when automobile designers became aware of the Y2038 bug, they developed newer automobile models using 64-bit integer values based code and ECUs (Electronic Control Units). Accordingly, modern automobile Electronic Control Units (ECUs) are based on a 64-bit architecture, and when used with time_t as a 64-bit integer, fix the Y2038 issue. This means that the anti-skid feature in a four-wheel drive will function correctly even after 2038.

Operating System

To avoid the Y2038 bug, use the 64-bit Linux distributions on 64-bit hardware. If using a 32-bit distribution such as the Debian 12 (Bookworm) stable release, it’s best to upgrade to a 64-bit one. Ubuntu has completely discontinued standalone 32-bit (x86/i386) installation images.

Software Applications

If one is already using software that uses the Unix time, it is best to update it to use one that uses a signed 64-bit integer to store date-time values, or at least an unsigned 32-bit integer to defer the issue till 2106.

Which Date-Time Functions to use? Use date-time functions that store value as a 64-bit signed integer. Database functions like the UNIX_TIMESTAMP() in MySQL (versions prior to 8.0.28) store timestamps as signed 32-bit integers; therefore, they become unusable after the Y2038 bug takes effect. Use MySQL 8.0.28 and later versions running on 64-bit platforms extend the valid range of argument values for UNIX_TIMESTAMP() that uses 64-bit signed decimal/integer (BIGINT).

Any legacy code that compares/stores date and time values using the signed 32-bit integers will fail, or provide erroneous results. For example, the time_t function in C language is a 32-bit based signed integer. To fix this, use the GNU C Library version 2.34, which adds support for 64-bit time_t on configurations like x86, where it is traditionally 32-bit. Internally it calls a new 64 bit signed integer implementation, _time64( __time64_t *destTime ). There is legacy support in the newer functions if needed. As an example, the new time_t function can be used as the old 32-bit time_t by defining the _USE_32BIT_TIME_T switch.

In Java, which has extensive use in embedded applications, the JVM's (Java Virtual Machine) System.currentTimeMillis() returns the result as a long primitive type (a signed 64-bit integer). Similarly, the java.time.Instant.getEpochSecond() function returns a signed 64-bit long representation of Unix seconds to avoid Y2038 integer truncation.

Further, use data types that support 64-bit signed integers to store data-time values, like the 64-bit Signed Integer (BIGINT) data type.

About The Author

Deepak is a Sun Certified Java Programmer and Web Component Developer, and has worked in the fields of XML, Java programming and Java EE for ten years. Deepak is the co-author of the Apress book Pro XML Development with Java Technology and was the technical reviewer for the O'Reilly book WebLogic: The Definitive Guide. Deepak was also the technical reviewer for the Course Technology PTR book Ruby Programming for the Absolute Beginner. Deepak is also the author of the Packt Publishing books JDBC 4.0 and Oracle JDeveloper for J2EE DevelopmentProcessing XML Documents with Oracle JDeveloper 11g, EJB 3.0 Database Persistence with Oracle Fusion Middleware 11g, and Java EE Development in Eclipse IDE. Deepak is a Docker Mentor and has published 5 books on Docker and Kubernetes.

Community Sponsor

Lets Hang!

User Comments

0 comments

English