2038年問題
(C)裏目小僧
(戻る)



time_tが将来64bitになるとしても、今現在のコンパイラでtime_tを使うと2038年には必ず問題が発生します。
明日出荷するソフトにtime_tを使うべきでしょうか?
当然場合により違うでしょう。
毎年のようにバージョンアップしてる現状で、かつ客先もそれに応じてくれてるなら64bitになるのを待てば良いでしょうね。
そうでなければ、time_tは捨てましょう。 自前で時間処理を書いてもそんなに大変ではありません。


《参考URL》
microsoft CTime および CTime の機能上の影響に関しての情報
時刻の扱い方(JAVA) 奥村晴彦先生の著です。リンクはご自由にとの記述で勝手にリンクさせて頂きました

GMTとUTCについての説明 http://202.224.39.49/~HI5K-STU/index_menu.htm から以下に
http://202.224.39.49/~HI5K-STU/compt/utc_gmt.htm

時刻と時間-----------TAI/UTC UNIXタイムについて精密な情報
http://tehanu.hpcl.titech.ac.jp/

プログラミングと暦--- 非常に詳細で精密な情報
http://www.kt.rim.or.jp/~tadf/programming-and-calendar.html


2038test.c(以下をダウンロードするならクリック)
/*****************************************************
 使っているコンパイラの日付処理が2038問題を抱えているか
 簡単なテストルーチンです。
  1.1971年〜 2106年迄 1日毎ににlocaltimeを呼び出してみる
  2.stimeで2100年にしてもてtimeで読んでみる
 だけです。
******************************************************/
#include <stdio.h>
#include <time.h>
#include <limits.h>
#define _DAY1 (24uL*60uL*60uL)
int DaysInYear(int y) /*西暦y年は何日あるか*/
{
 if( (y%4)!=0) return 365;  /*4で割れなければ必ず1年は365日*/
 if( (y%400)==0) return 366;/*400で割れた年は 閏*/
 if( (y%100)==0) return 365;/*100で割れた年は 365日*/
 return 366;                /*でなければ閏*/
}
int DaysInMonth(int y,int m) /*西暦y年m月は何日あるか*/
{                     
 if(DaysInYear(y)==365)    /*1  2  3  4  5  6  7  8  9 10 11 12*/
  {const static char tbl[]={31,28,31,30,31,30,31,31,30,31,30,31};
   return tbl[m-1];
  }else
  {static const char tbl[]={31,29,31,30,31,30,31,31,30,31,30,31};
   return tbl[m-1];
  }
}
int YDAYtoMM(int y,int d) /*西暦y年の元旦から何日目は何月か*/
{  int m=1;
   while(d>=DaysInMonth(y,m))d-=DaysInMonth(y,m++);
   return m;
}
int YDAYtoDD(int y,int d) /*西暦y年の元旦から何日目は月の何日か*/
{  int m=1;
   while(d>=DaysInMonth(y,m))d-=DaysInMonth(y,m++);
   return d+1;
}

int main()
{
struct tm tm1;
time_t time1,savet; 
int  y,d;
int flag=0,ey,ed;
 if(sizeof tm1 == 32/CHAR_BIT )
   { printf("time_tは%dbit環境です\n",(sizeof(time_t))*CHAR_BIT);
     printf("%s\n","判定は出来ませんが、まず大丈夫でしょう");
     return 1;
   }
 if((time_t)-1 > 0)  printf("%s\n","time_tは符号無し整数環境です");

 time1=_timezone +(time_t)DaysInYear(1970)*_DAY1;  
 for(y=1971;y<2106;y++)
  {
  printf("%4d",y);
    for(d=0;d<DaysInYear(y);d++,time1+=_DAY1)
    {
     tm1=*localtime(&time1);
     if(tm1.tm_year+1900!=y 
     || tm1.tm_mday  != YDAYtoDD(y,d)
     || tm1.tm_mon +1!= YDAYtoMM(y,d) )  
     if(flag==0) { flag=2;ey=y,ed=d; }
    }
  printf("%s","\b\b\b\b");
  }
 if(flag)
   printf("localtimeは%d年%d月%d日から正しくない\n",
                      ey,YDAYtoMM(ey,ed),YDAYtoDD(ey,ed));
   
  printf("%s\n","--今から日付をctimeで2100年1月1日に変更してみます--!!");
  {char buf[8]; fgets(buf,7,stdin);}
  time(&savet);
  time1=_timezone + (47482uL*_DAY1);
  stime(&time1);  time(&time1);
  printf("ctime=%s\n",  ctime(&time1));
  stime(&savet);
 if( (unsigned long)time1-(unsigned long)(47482uL*_DAY1) > 3)
   {
    printf("%s\n","stimeで2100年を設定出来ないかtimeが正しくない");
    return 3;
   }
 return flag;
}


本資料参照数 =