On January 19, 2038, RecAll-PRO (and RecAll and to a lesser extent VCRadio) will display a bug. (Of course, we will issue a software update well before then to correct the problem.) A number of other programs from other companies will also develop problems. It won’t make big news like Y2K, but it is a detail needing correction in multiple software packages. Why 2038? How did we come to this? Why didn’t we fix this when fixing Y2K?
The discussion gets a bit technical, so if you aren’t familiar with binary arithmetic, feel free to skip ahead.
The Problem
The C run-time library, widely used by C and C++ programmers, provides a function for reading the current time:
- time_t time(time_t *timer);
which returns the time as elapsed seconds since midnight January 1, 1970, the year that Unix first ran on a PDP-11/20 machine. In the parlance of programmers, time_t is a type definition, with data size not defined by the Posix standard but typically implemented as a 32 bit signed integer. The maximum date that coud be specified with this representation is Tuesday, January 19, 2038. Increment past that date and the variable will “overflow” to a negative number, representing the year 1901.
Using a time/date system representing seconds from a known obscure date might seem eccentric to non-programmers, but coders do this sort of thing all the time. The Windows operating system defines a FILETIME variable as a signed 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601. (Why 1601?) Java Date uses a signed 64-bit integer counting milliseconds from January 1, 1970. .NET DateTime uses an unsigned 62 bit (yes, 62) integer counting 100 nanosecond ticks from January 1, year 0001.
RecAll-PRO (and RecAll and VCRadio) use Unix time to store timecodes for audio files, to represent the date and time when sound was recorded. A number of other programs will also affected by the problem, variously known as Y2038 or Y2.038K.
Testing
Setting the computer clock forward to February 2038, we verify that RecAll-PRO has problems displaying the proper time. The date display fails, so RecAll-PRO “gracefully” degrades to displaying relative time position.
We wanted to know if our current C compiler could use time_t variables larger than 32 bits, or could work with a 32 bit unsigned number, so we could extend beyond year 2038, so we wrote a quick test program. The answer is NO.
Out of curiosity, we wrote a quick program to display the maximum FILETIME possible. Unfortunately, the FileTimeToSystemTime function only works for half the maximum range of FILETIME, so we use that instead:
#include <stdio.h>
#include <windows.h> int main(int argc, char* argv[])
{
FILETIME ft;
// MSDN: “The FileTimeToSystemTime function only works with FILETIME values
// that are less than 0x8000000000000000.”
ft.dwHighDateTime = 0x7ffffffful;
ft.dwLowDateTime = 0xfffffffful;SYSTEMTIME st;
if (FileTimeToSystemTime(&ft,&st))
printf(“Maximum filetime date: month=%d day=%d, year=%d\n”, st.wMonth,st.wDay, st.wYear);return 0;
}
Maximum filetime date: month=9 day=14, year=30828
Press any key to continue
Year 30828 should be large enough for our purposes. 🙂 If you need larger dates, please let us know.
The Fix
We use a Microsoft C++ compiler for development work, but not their most recent product. Microsoft documentation notes that Visual C++ 2005 is the first Microsoft compiler to use signed 64 bit integers for the time() function, which should fix the problem.
If we decide not to update compilers, we could write our own version of time() that accepts 64 bit integers, perhaps using FILETIME internally.
Year 30828 isn’t a terrible hack, but I still think the more elegant solution is to make time_t a 64-bit signed variable, so we’ll be able to time the time burning out. 🙂
Interesting article!
Cheers,
Wills