What should we do to prepare for 2038?
Asked Answered
O

11

67

I would like to think that some of the software I'm writing today will be used in 30 years. But I am also aware that a lot of it is based upon the UNIX tradition of exposing time as the number of seconds since 1970.

#include <stdio.h>
#include <time.h>
#include <limits.h>

void print(time_t rt) {
    struct tm * t = gmtime(&rt);
    puts(asctime(t));
}

int main() {
    print(0);
    print(time(0));
    print(LONG_MAX);
    print(LONG_MAX+1);
}

Execution results in:

  • Thu Jan 1 00:00:00 1970
  • Sat Aug 30 18:37:08 2008
  • Tue Jan 19 03:14:07 2038
  • Fri Dec 13 20:45:52 1901

The functions ctime(), gmtime(), and localtime() all take as an argument a time value representing the time in seconds since the Epoch (00:00:00 UTC, January 1, 1970; see time(3) ).

I wonder if there is anything proactive to do in this area as a programmer, or are we to trust that all software systems (aka Operating Systems) will some how be magically upgraded in the future?

Update It would seem that indeed 64-bit systems are safe from this:

import java.util.*;

class TimeTest {
    public static void main(String[] args) {
        print(0);
        print(System.currentTimeMillis());
        print(Long.MAX_VALUE);
        print(Long.MAX_VALUE + 1);
    }

    static void print(long l) {
        System.out.println(new Date(l));
    }
}
  • Wed Dec 31 16:00:00 PST 1969
  • Sat Aug 30 12:02:40 PDT 2008
  • Sat Aug 16 23:12:55 PST 292278994
  • Sun Dec 02 08:47:04 PST 292269055

But what about the year 292278994?

Orbicular answered 30/8, 2008 at 18:42 Comment(7)
You would be happy if you were present to be held responsible for some accident by that year, wouldn't you?Sanguinary
Don't worry about year 292278994. Most systems fail at year 2147483647.Stanger
I think that you've convinced us - we need to move to 128 bit immediately!Pietism
The world ends in 2012, why would you need to measure any time past that?Memnon
By that time the sun is a red giant and humanity is gone :DEmiliaemiliaromagna
Hello from 2021! Linux 5.6 and above are ready to run past year 2038 on 32-bit systems: lkml.org/lkml/2020/1/29/355?anz=webFalcongentle
some one may find this answer useful: get a Y2038 safe buildroot 32-bit ARM systemCousingerman
S
49

I have written portable replacement for time.h (currently just localtime(), gmtime(), mktime() and timegm()) which uses 64 bit time even on 32 bit machines. It is intended to be dropped into C projects as a replacement for time.h. It is being used in Perl and I intend to fix Ruby and Python's 2038 problems with it as well. This gives you a safe range of +/- 292 million years.

You can find the code at the y2038 project. Please feel free to post any questions to the issue tracker.

As to the "this isn't going to be a problem for another 29 years", peruse this list of standard answers to that. In short, stuff happens in the future and sometimes you need to know when. I also have a presentation on the problem, what is not a solution, and what is.

Oh, and don't forget that many time systems don't handle dates before 1970. Stuff happened before 1970, sometimes you need to know when.

Stanger answered 20/10, 2008 at 2:5 Comment(8)
@Schwern: Also, September 1752 is a month with fewer than 28 days. Niche knowledge thanks to the Pragmatic Programmer. genealogytoday.com/columns/everyday/030902.htmlTropaeolin
@Dave Oh ho, depends on your locality! Only the British and possessions switched to Gregorian in 1752. Others did in 1582 all the way up to the 20th century (Eastern Europe, China, Turkey, Russia). ncal -p for a list and en.wikipedia.org/wiki/Gregorian_calendar#Adoption for the full story. Also there's no year 0... unless you're talking to an astronomer. Hopefully you never have to deal with the Julian/Gregorian conversion.Stanger
@pm100: "The source control for this project has moved to github and is now using git." : github.com/schwern/y2038Hirsute
tx - what do i do for time_t now = time(0)?Elastance
Schwern, people like you are my heroes.Mancilla
@Elastance It only just sunk in what you were really asking. The y2038 library does not provide a replacement function for time(), you just use time(). Why? Because it can't fix the system clock. If you're still on a machine with a 32 bit clock in 2038 you're screwed. What you're likely to start seeing as we get closer and closer to 2038 is hacks that do things like "if the time is < 1.5billion then add 4billion to it" similar to y2k fixes that said "if the year is between 00 and 30 assume its 2000 - 2030".Stanger
i thought u missed my point. Maybe a time64 that returns a 64 bit time that at least makes sure I have a 64 bit time value (even if the kernel is returning 32 bit). THat way I have clean code that works in both 32 and 64 bit cases (32 bit case will die in 2038). I can then grep out all include time.hElastance
@Elastance Generally you'd just cast it, but I see value in having a time64() that calls time() and casts it to Time64_T. It could also do some bounds checking, error or warn if time() returns a negative number.t. Put it up as an issue please? code.google.com/p/y2038/issues/list And feel free to implement it.Stanger
I
19

You can always implement RFC 2550 and be safe forever ;-)

The known universe has a finite past and future. The current age of the universe is estimated in [Zebu] as between 10 ** 10 and 2 * 10 ** 10 years. The death of the universe is estimated in [Nigel] to occur in 10 ** 11 - years and in [Drake] as occurring either in 10 ** 12 years for a closed universe (the big crunch) or 10 ** 14 years for an open universe (the heat death of the universe).

 

Y10K compliant programs MAY choose to limit the range of dates they support to those consistent with the expected life of the universe. Y10K compliant systems MUST accept Y10K dates from 10 ** 12 years in the past to 10 ** 20 years into the future. Y10K compliant systems SHOULD accept dates for at least 10 ** 29 years in the past and future.

Impeachment answered 25/10, 2008 at 21:39 Comment(5)
That's the only LONG-LASTING solution I've seen so far.Sanguinary
Ah, but that's only the estimated age of the universe. If that estimate is a little off, we're in big trouble!Budbudapest
The only real solution is to store time in Plank time units out to the point where all protons and neutrons will have evaporated, about 1e40 years which will take a bit more than 256 bits to store. But since proton decay is still a hypothesis and the exact number is not known, push it up to 512 bits just to be safe. mail.pm.org/pipermail/pdx-pm-list/2010-September/005952.htmlStanger
+1 for pointing to an RFC that has both made me laugh and made me start coding~Arndt
the main issue is getting time from the system and not the representation. If the OS or the libc suffers Y2K38 then the program will also suffer it when it needs the current timeHelsie
B
4

Visual Studio moved to a 64 bit representation of time_t in Visual Studio 2005 (whilst still leaving _time32_t for backwards compatibility).

As long as you are careful to always write code in terms of time_t and don't assume anything about the size then as sysrqb points out the problem will be solved by your compiler.

Bev answered 30/8, 2008 at 18:49 Comment(1)
Their localtime() and gmtime() implementations do not work before 1970 and fail in year 3001. See code.google.com/p/y2038/wiki/AmazingDiscoveriesStanger
V
1

I think that we should leave the bug in. Then about 2036 we can start selling consultancy for large sums of money to test everything. After all isn't that how we successfully managed the 1999-2000 rollover.

I'm only joking!

I was sat in a bank in London in 1999 and was quite amazed when I saw a consultant start Y2K testing the coffee machine. I think if we learnt anything from that fiasco, it was that the vast majority of software will just work and most of the rest won't cause a melt down if it fails and can be fixed after the event if needed. As such, I wouldn't take any special precautions until much nearer the time, unless you are dealing with a very critical piece of software.

Velleman answered 25/3, 2009 at 17:42 Comment(3)
Y2K was not a problem because people prepared for it. The run-up involved a whole lot of work. The vast majority of software didn't just work, it was examined and perhaps fixed. The other stuff didn't cause a meltdown because there wasn't that much of it.Hypnos
David is correct. Enterprises that took the y2k problem seriously, had a thorough review of virtually all their systems. Problems were found, and fixed. As part of a smaller non-critical system - we fixed 3 problems, all of which would have led to data-loss had they not been fixed.Jenelljenelle
Let me be clear, I am not saying we should do nothing. I just think we can test far fewer systems than the consultants will suggest and blanket "we must test everything" policies are over the top. Let's just stick to the mission critical stuff this time.Velleman
S
1

Given my age, I think I should pay a lot into my pension and pay of all my depts, so someone else will have to fit the software!

Sorry, if you think about the “net present value” of any software you write today, it has no effect what the software does in 2038. A “return on investment” of more than a few years is uncommon for any software project, so you make a lot more money for your employer by getting the software shipped quicker, rather than thinking that far ahead.

The only common exception is software that has to predict future, 2038 is already a problem for mortgage quotation systems.

Seriatim answered 3/10, 2010 at 16:33 Comment(0)
C
1

I work in embedded and I thought I would post our solution here. Our systems are on 32 bits, and what we sell right now has a warantee of 30 years which means that they will encounter the year 2038 bug. Upgrading in the future was not a solution.

To fix this, we set the kernel date 28 years earlier that the current date. It's not a random offset, 28 years is excatly the time it will take for the days of the week to match again. For instance I'm writing this on a thursday and the next time march 7 will be a thursday is in 28 years.

Furthermore, all the applications that interact with dates on our systems will take the system date (time_t) convert it to a custom time64_t and apply the 28 years offset to the right date.

We made a custom library to handle this. The code we're using is based off this: https://github.com/android/platform_bionic

Thus, with this solution you can buy yourself an extra 28 years easily.

Charlenacharlene answered 7/3, 2017 at 20:0 Comment(2)
I've meen using March 1, 2000 as an epoch date in embedded systems for over a decade (treating March 1 as a new year, but then saying if (month > 12) { month-=12; year++; } means that if code starts with a "div/mod 1461", each leap day will be day 1460 of a 4-year interval, and leap years can otherwise be ignored Nowadays it might make sense to use March 1, 2016 and soon it might make sense to use March 1, 2020, but even 2000 is 30 years better than 1970.Westberg
See my post too - in my embedded project, time_t is simply 64bit ,and the time functions support it. Aside from a small performance penalty, there is no need for any trickeryPereyra
K
0

Keep good documentation, and include a description of your time dependencies. I don't think many people have thought about how hard this transition might be, for example HTTP cookies are going to break on that date.

Kochi answered 30/8, 2008 at 18:43 Comment(0)
S
0

What should we do to prepare for 2038?

Hide, because the apocalypse is coming.

But seriously, I hope that compilers (or the people who write them, to be precise) can handle this. They've got almost 30 years. I hope that's enough time.

At what point do we start preparing for Y10K? Have any hardware manufacturers / research labs looked into the easiest way to move to whatever new technology we'll have to have because of it?

Subscribe answered 28/3, 2009 at 7:48 Comment(0)
P
0

Note that I ran into your post on a 32bit MCU, and ran your code with my compiler, which also produced the overflow to 1970, and mistakenly assumed I needed the library like the one from the y2038 project.

One should however do this to verify (note the time_t cast):

printtime(0);
printtime(time(0));
printtime(((time_t)LONG_MAX));
printtime(((time_t)LONG_MAX)+1);

In my case, time_t is actually defined as a __int_least64_t => uint64_t, and the native gmtime function takes 64bit as input, so works just fine after 2038. However, when not casting, my compiler did print a warning which I stupidly missed:

integer overflow in expression of type 'long int' results in '-2147483648' [-Woverflow]

Note that just casing to (uint32_t) was also enough, but without casting, the compiler executed LONG_MAX+1 as a signed int, causing an overflow. Only afterwards the compiler then casts the -1 result to the time_t of the calling function, which is still wrong. That confusingly seems to indicate that the gmtime is not 64bit, but that's a wrong conclusion

Long story short: My libc time functions were already 64bit (even on a 32bit MCU), but your post threw off, thinking I needed additional libraries (which were not needed). (Basically an equivalent of the y2038 code was already in there)

Pereyra answered 27/10, 2023 at 8:33 Comment(0)
C
-2

By 2038, time libraries should all be using 64-bit integers, so this won't actually be that big of a deal (on software that isn't completely unmaintained).

COBOL programs might be fun though.

Castroprauxel answered 30/8, 2008 at 18:45 Comment(4)
Consider when a new 30 year mortgage on a house ends.Stanger
First encounter I had was with working with child support payments in 1981. The system took the anticipated birth date of the child, in 1982, added 18, got 0, noticed that 81 > 0, and figured the obligation was over. As you say, banks got into this mess earlier.Hypnos
@Schwern: and you think 30-year mortgage documentation uses time_t values storing # seconds since 1970?Amero
Even on software that's maintained, if it stores a timestamp in a fixed offset in the file format (as many that I've seen do), you'll need a new non-backwards-compatible file format. Or what about my iPod -- I can't get latest firmware upgrades for a 9-year-old iPod, so I don't think there's going to be much hope for a 28-year-old iPod. Or the antilock break system in my car. Just because software is maintained doesn't mean it's going to be easy to upgrade everybody.Anhydride
G
-8

Operative word being "should".

If you need to ensure futureproofing then you can construct your own date/time class and use that but I'd only do that if you think that what you write will be used on legacy OS'

Grisham answered 30/8, 2008 at 18:47 Comment(4)
Time zones are very, very, very hard to handle on your own. Also, just about every OS and many languages have this problem, even those running on 64 bit hardware. Like that 64 bit CPU in your shiny new Mac which still uses 32 bit time.Stanger
I seem to always favor the "role your own" solutions, even if no one else does. :-)Orbicular
I like the way that I have the accepted answer and 4 downvotes :DGrisham
This answer reminds me of all the custom written leap year detection code that failed in 2000.Stanger

© 2022 - 2024 — McMap. All rights reserved.