2038年問題のソースを表示
←
2038年問題
ナビゲーションに移動
検索に移動
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループに属する利用者のみが実行できます:
登録利用者
。
このページのソースの閲覧やコピーができます。
{{出典の明記|date=2015年7月}} '''2038年問題'''(にせんさんじゅうはちねんもんだい)は、[[協定世界時]](UTC)[[2038年]][[1月19日]]3時14分7秒([[日本標準時]]の場合、1月19日12時14分7秒)を過ぎると、[[コンピュータ]]が誤動作する可能性があるとされる[[年問題]]。 == 経緯 == [[ファイル:Year 2038 problem.gif|right|upright=2.0|thumb|上から、2進・十進・問題のある時刻・正しい時刻。([[GIFアニメ]])3時14分7秒を超えたところで負の値となり、時刻に狂いが生じる恐れがある。]] コンピュータおよび[[プログラム (コンピュータ)|コンピュータプログラム]]における[[時刻]]の表現として「[[UNIX時間]]」《[[協定世界時]]における1970年1月1日0時0分0秒からの経過秒数{{efn|「ただし、うるう秒を無視して現在時刻から逆算した値を使用する」として運用されていることが専らである。}}》を採用しているシステムがある。 [[UNIX]]およびUNIX派生の[[オペレーティングシステム]] (OS) における基幹[[ソフトウェアコンポーネント|ソフトウェア部品]]の多くは[[C言語]]で書かれているが、前述の経過秒数を表現する型は、現在の標準では、「[[time_t]]型」である。[[C言語]]の標準である「ISO/IEC 9899:1999」では、<code>time_t</code>型の範囲や精度はいずれも実装定義としている<ref>"The range and precision of times representable in clock_t and time_t are implementation-defined.", ISO/IEC 9899 7.23.1.4</ref>。UNIXの標準 ([[POSIX]]) には「shall be integer or real-floating types.」とのみ記述があり、ビット幅および値の範囲については何らの定めも無い。 伝統的な実装では<code>time_t</code>を<code>int</code>または<code>long</code>の[[typedef]]による型エイリアス(別名)とし、その型は符号付き[[32ビット]]整数型であった。このため最大値は (2<sup>31</sup> − 1) = 2,147,483,647 となり、取り扱えるのは2,147,483,647秒(≒ 68年)までに限られていた。これを前提として作成されたプログラムは、協定世界時における'''1970年1月1日0時0分0秒'''([[日本標準時]]では1970年1月1日9時0分0秒)から'''2,147,483,647秒'''を経過した、'''2038年1月19日3時14分7秒'''(日本標準時では2038年1月19日12時14分7秒、[[閏秒]]は考慮していない)を過ぎると、この値が[[算術オーバーフロー|オーバーフロー]]し{{efn|Cではオーバーフロー発生時の動作は未定義。整数が[[2の補数]]でオーバーフローした値が[[負の整数|負]]と扱われる場合、2038年1月19日3時14分7秒の次は'''1901年12月13日20時45分52秒'''となる。}}、もし時刻を正しく扱えていることを前提としたコードがあれば、誤動作する。 ある実装における<code>time_t</code>の型を変更することだけであれば、プログラム中のたった1箇所 ([[typedef]]) を書き換えるだけであるが、実際の運用では、アプリケーションプログラムにおける時刻の扱い全てが正しくある必要がある。また、すでにあるデータ構造中で32ビット固定長として割り当てられていれば、問題が発生する。たとえば、Linuxの[[ファイルシステム]]である[[ext2]]・[[ext3]]・[[ReiserFS]]の[[タイムスタンプ]]は同日付までしか対応していない。 この期日以前でもプログラムで内部的にこの制限を超えた時刻データを扱おうとすれば同様のエラーが発生するため、たとえばちょうど半分を経過した2004年1月11日にはすでに[[現金自動預け払い機|ATM]]の誤動作といったトラブルが発生した<ref>{{Cite news|author=大和田尚孝|url=https://xtech.nikkei.com/it/free/NC/NEWS/20040202/139212/ |title=コンピュータの“西暦2038年問題”発生、早くも日本を揺るがす|publisher=[[日経コンピュータ]]|date=2004-02-02}}</ref>。この事例ではプログラム中のある時刻と別の時刻の中間の時刻を求めるような処理で、相加[[平均]]を単純に求める <math>(t_1 + t_2) / 2</math> のような式を利用していたものとみられる{{efn|計算機による計算においては、このような一見して何の変哲もない式によるバグは入力数値がある程度大きくならないと露呈しにくく、この問題に限らず普遍的なものであり、一般に注意を要する。}}。他にも顕在化していないトラブルが今後表面化するという可能性はあり得る。 [[2000年問題]]はアプリケーションレベルでの修正が可能であったが、この問題は現在普及しているC言語[[処理系]]やOSのAPIといったシステムの深い層に潜む問題であるため、2000年問題より深刻であるという指摘もある<ref name="change-makers.jp/technology/11351">{{Cite web|和書|title=2025年問題の次は2038年問題!コンピュータの暦問題を探る(後編)|author=CHANGE-MAKERS|url=https://www.change-makers.jp/technology/11351|access-date=2018-11-20}}</ref>。 == 対策 == 対策としては、<code>time_t</code>型を符号付き64ビット整数型(一般には'''<code>long long int</code>型''')にするという方法がある。符号付き64ビット整数型の場合、上限は'''{{val|9223372036854775807|fmt=commas}}'''({{2^|63}} − 1)である。これを年数に変換するとおよそ西暦3000億年{{efn|{{val|9223372036854775807|fmt=commas|u=秒}} ÷ (60<sup>2</sup> × 24 × 365.2425) ≒ {{val|2.9228e11}}年 ≒ 3000億年。これは[[太陽系]]の寿命よりもはるかに長い([[太陽]]の[[白色矮星]]化は西暦68億年ごろ)。}}まで使用できるので、事実上問題が発生することはない。64ビット版の[[オペレーティングシステム]]や[[処理系]]では、<code>time_t</code>型は符号付き64ビット整数型で表されるようになってきている。UNIXベースのOSでは、64ビット版で<code>time_t</code>も併せて64ビット化されることが多い。 何らかの事情により<code>time_t</code>を64ビット化できない環境に対しては、<code>time_t</code>を符号無し32ビット整数型(一般的には'''<code>unsigned long int</code>型''')にするという回避策が使われることもある。この場合、上限は'''{{val|4294967295|fmt=commas}}'''({{2^|32}} − 1)となり、[[2106年]]2月7日6時28分15秒(閏秒を考慮しない場合)まで表現可能になる。従って2038年問題は回避できるが、結局2106年には問題が発生するため、あくまで64ビット化が困難な環境に限って適用すべき方法とされる。 [[macOS]] ([[Mac OS X]] 10.0) では<code>NSDate</code>クラスにて[[協定世界時]]の2001年1月1日0時ちょうどをエポックタイムとして刷新し<ref>[https://developer.apple.com/documentation/foundation/nsdate?language=objc NSDate - Foundation | Apple Developer Documentation]</ref><ref>[https://developer.apple.com/library/prerelease/content/documentation/CoreFoundation/Conceptual/CFDatesAndTimes/Concepts/DataReps.html#//apple_ref/doc/uid/20001139-CJBEJBHH Date Representations]</ref>、また経過時間の内部表現として[[倍精度浮動小数点数]]を用いるようになったため<ref>[https://developer.apple.com/documentation/foundation/nstimeinterval NSTimeInterval | Apple Developer Documentation]</ref>、これらを使用している限り、2038年については問題を回避できる。なお、[[macOS Mojave]]は32ビットアプリケーションを動作させることのできる最後のバージョンとなり、[[macOS Catalina]]では起動することができなくなった<ref>[https://support.apple.com/ja-jp/103076 32 ビット App と macOS High Sierra 10.13.4 以降の互換性 - Apple サポート]</ref>。 32ビット版の[[Microsoft Windows]] (Win32) では内部時刻の表現に64ビット化された<code>FILETIME</code>構造体<ref>[https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime FILETIME (minwinbase.h) - Win32 apps | Microsoft Docs]</ref>を使っており、<code>time_t</code>を使っているわけではない。そのため、Windows OS側に関しては、旧OSに関する一部のケースを除き<ref>[https://web.archive.org/web/20060626085939/http://support.microsoft.com/kb/436249/JA/ システム日付が 2038 年以降に設定されていると、Windows XP のセットアップが途中で停止する場合がある], [[Internet Archive]]</ref><!-- Windows XP SP3 では解消されているのかもしれないが、未確認。 -->、32ビット版であっても2038年問題は発生しない<ref>[https://learn.microsoft.com/en-us/archive/blogs/mthree/another-look-at-the-year-2038-problem Another look at the year 2038 problem | Microsoft Docs]</ref>。ただし、Microsoft C/C++ (MS-C) および古いバージョンの[[Microsoft Visual C++]] (MSVC) においては、<code>time_t</code>は32ビットの<code>long int</code>を使って定義されていたため、これらの古い処理系のC/C++ランタイムライブラリ (CRT) を利用して構築された[[アプリケーションソフトウェア]]や[[DLL]]などは、2038年問題を抱えていることになる。[[x64]]アーキテクチャの64ビット版Windows OS上では[[WOW64]]サブシステムにより[[x86]]アーキテクチャ向けに構築された32ビットアプリケーションも動作させることができるが、古い32ビットアプリケーションにおける2038年問題は、たとえWindows OSを64ビット版に入れ替えたとしても回避することはできない。[[Microsoft Visual C++]] 2005以降では、既定で<code>time_t</code>は<code>__time64_t</code>と等しく<ref>[https://docs.microsoft.com/en-us/cpp/c-runtime-library/time-management Time Management | Microsoft Docs]</ref>、32ビットアプリケーションであっても<code>time_t</code>は64ビット化されるため、古いアプリケーションを新しい処理系およびランタイムで構築し直せば2038年問題を回避できる。 == 関連した問題 == *時刻aと時刻bのちょうど中間の時刻を求める時、それぞれのUnixタイムをTaとTbとして、(Ta+Tb)/2 と計算すると、2038年問題の半分以降が経過していればTa+Tbの計算で[[算術オーバーフロー|オーバーフロー]]し、誤った結果となる。これは{{val|1073741824|fmt=commas|u=秒}}目で、2004年1月10日13時37分4秒以降がこの場合に相当する。2004年1月10日あるいは11日に、この事例と推察される報告があった<ref> {{Cite news|url=https://xtech.nikkei.com/it/members/NC/ITARTICLE/20040325/1/ |title=「西暦2038年問題」でトラブル相次ぐ|publisher=[[日経コンピュータ]]|author=|date=2004-04-01}}</ref>。 この問題を回避するためには、計算方法を工夫する必要がある。例えば、時刻の中間を求める際に、オーバーフローを避けるために次のような方法が考えられる: *# '''時刻の差を計算する''': まず、時刻bから時刻aを引いて、その差を求める。 *# '''差の半分を求める''': 求めた差を2で割る。 *# '''時刻aに加える''': 最後に、時刻aに差の半分を加えることで、中間の時刻を求める。 この方法を数式で表すと、次のようになる: 中間時刻=''Ta''+(''Tb''−''Ta'')/2 == 類似する年問題 == {{Main|年問題}} *[[2001年9月9日問題]]は、2001年9月9日にtime_t型の値が9億秒から10億秒と桁が増えることに伴う問題。time_t型の値を文字列(辞書順)でソートしていたことで、「9億 > 10億」と判断され、項目の新旧が正しく判断されず、新しく作られた項目が表示されない、古いものとみなされ削除されるなどの問題が発生した。 *[[Network Time Protocol|NTP]]など、1900年1月1日からの積算秒数で時間を表現するシステムもあり、符号なし32ビットの値が[[2036年]][[2月7日]]6時28分15秒 (UTC) を超えるとオーバーフローすることによって問題が発生する(→[[Network Time Protocol#2036年問題|2036年問題]])。[[Simple Network Time Protocol|SNTPv4]]を定めた<nowiki/>{{IETF RFC|4330}}<nowiki/>には、最上位ビットが0の場合は時刻が2036年から2104年の間であるとみなして、2036年2月7日6時28分16秒 (UTC) を起点として計算することで2036年問題を回避する方法が書かれている。 *2038年4月23日問題 - [[ユリウス通日]]を内部日付表現に用いる物のうち、基準日([[グレゴリオ暦]]1858年11月17日正午)からの修正ユリウス日(MJD)を使用し、かつ16ビットで処理しているシステムでは、日数が16ビットからあふれるために問題が起こる。 == 脚注 == {{脚注ヘルプ}} === 注釈 === {{Notelist}} === 出典 === {{Reflist}} == 関連項目 == *[[UNIX時間]] *[[ジョン・タイター]] *[[2000年問題]] == 外部リンク == *[http://sunpillar.jf.land.to/bekkan/javascript/2038.shtml#TIMER 2038年問題へのカウントダウン]{{Ja icon}} {{年問題}} {{DEFAULTSORT:2038ねんもんたい}} [[Category:2038年]] [[Category:UNIX]] [[Category:コンピュータ史]] [[Category:日時の表現法に起因するバグ|2038]] [[Category:未来問題]]
このページで使用されているテンプレート:
テンプレート:2^
(
ソースを閲覧
)
テンプレート:Cite news
(
ソースを閲覧
)
テンプレート:Cite web
(
ソースを閲覧
)
テンプレート:Efn
(
ソースを閲覧
)
テンプレート:IETF RFC
(
ソースを閲覧
)
テンプレート:Ja icon
(
ソースを閲覧
)
テンプレート:Main
(
ソースを閲覧
)
テンプレート:Notelist
(
ソースを閲覧
)
テンプレート:Reflist
(
ソースを閲覧
)
テンプレート:Val
(
ソースを閲覧
)
テンプレート:出典の明記
(
ソースを閲覧
)
テンプレート:年問題
(
ソースを閲覧
)
テンプレート:脚注ヘルプ
(
ソースを閲覧
)
2038年問題
に戻る。
ナビゲーション メニュー
個人用ツール
ログイン
名前空間
ページ
議論
日本語
表示
閲覧
ソースを閲覧
履歴表示
その他
検索
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
特別ページ
ツール
リンク元
関連ページの更新状況
ページ情報