unix time と2038年問題

「不正な時刻が悪さをする」ということで聴いてみると、いわゆるunix timeとして正しく扱えないということのよう。ライブラリがエラーを返すらしい。とあるRTOSの開発環境の話であるけれども、手元にコンパイラでどうなるか調べてみました。

Visual C++ 2005

time_t が8バイトに拡張されていて、2038年問題は起きなくなってます。
が、-1を指定してctime()を呼び出すと不正割り込み発生。
ctime()では値として 0x0000000793406fff - Thu Jan 01 07:59:59 3001 までが正しく扱える範囲ですね。

sizeof(time_t) is 8 bytes
sizeof(time_t) is 8 bytes
0x0000000000000000 - Thu Jan 01 00:00:00 1970
0x000000007ffffffe - Tue Jan 19 03:14:06 2038
0x000000007fffffff - Tue Jan 19 03:14:07 2038
0x0000000080000000 - Tue Jan 19 03:14:08 2038
0x0000000080000001 - Tue Jan 19 03:14:09 2038
0x00000000ffffffff - Sun Feb 07 06:28:15 2106

Borland C++ 5.82

負数の範囲は正しく扱えない模様。

sizeof(time_t) is 4 bytes
0x00000000 - Thu Jan 01 00:00:00 1970
0x7ffffffe - Tue Jan 19 03:14:06 2038
0x7fffffff - Tue Jan 19 03:14:07 2038
0x80000000 - (null)
0x80000001 - (null)
0xffffffff - (null)

g++ on Linux

負数は1970年1月1日から遡っていく仕様。

sizeof(time_t) is 4 bytes
0x00000000 - Thu Jan  1 00:00:00 1970
0x7ffffffe - Tue Jan 19 03:14:06 2038
0x7fffffff - Tue Jan 19 03:14:07 2038
0x80000000 - Fri Dec 13 20:45:52 1901
0x80000001 - Fri Dec 13 20:45:53 1901
0xffffffff - Wed Dec 31 23:59:59 1969

確認したプログラム

#ifdef __BORLANDC__
#include <stdio.h>
#include <time.h>
#define putenv(s)   { _timezone = 0; }
#else
#include <cstdio>
#include <ctime>
#include <cstdlib>
#ifdef _MSC_VER
#define putenv(s)   _putenv(s)
#endif
#endif

void show(time_t t)
{
    if (sizeof(time_t) == 8) {
        printf("0x%016llx - ", static_cast<long long>(t));
    } else {
        printf("0x%08x - ", t);
    }
    char *p = ctime(&t);
    if (p) {
        printf(ctime(&t));
    } else {
        puts("(null)");
    }
}

int main()
{
    putenv("TZ=GMT");

    printf("sizeof(time_t) is %d bytes\n", sizeof(time_t));
    show(0);
    show(0x7ffffffe);
    show(0x7fffffff);
    show(0x80000000);
    show(0x80000001);
    show(0xffffffff);
}