2000年問題も気付けば20年以上前で、2038年問題が近付いてきている今日この頃ですが、今回は3001年問題のお話です。
3001年問題や、その前身の3000年問題については下記のサイトを参照してください。
簡単に言うと、 time_t 型自体は 64 ビットあり2000億年以上を扱えるのに*1、 Visual C++ の時間関数群の実装ではなぜか 3001 年以降を扱えないようにキャップされてしまっているという問題です。
キャップ無しだとそれはそれでセキュリティ上問題がありそうですが、それにしたってもう少し大きい値でキャップしてもいいような気がしますね。
そんな3001年問題ですが、具体的に各関数の引数値の許容範囲を調べてみたところ、使用する関数やVC++のバージョンによって値に差があることがわかりました。
私が調べたのは2012、2013、2015、2017、2019ですが、2013以前と2015以降で変化があったようです。
関数 | VC++バージョン | 引数値の許容範囲 | 備考 | |
---|---|---|---|---|
最小 | 最大 | |||
gmtime, gmtime_s | 2012, 2013 | -43200 | 32535291599 | 作成値は 1969/12/31 12:00:00 〜 3001/01/01 20:59:59 |
2015, 2017, 2019 | -43200 | 32536850399 | 作成値は 1969/12/31 12:00:00 〜 3001/01/19 21:59:59 | |
localtime, localtime_s | 2012, 2013 | 0 | 32535244799 | 作成値は 1970/01/01 00:00:00 〜 3001/01/01 07:59:59 (UTC換算) |
2015, 2017, 2019 | 0 | 32536799999 | 作成値は 1970/01/01 00:00:00 〜 3001/01/19 07:59:59 (UTC換算) |
関数 | VC++バージョン | 引数値の許容範囲(UTC換算) | 備考 | |
---|---|---|---|---|
最小 | 最大 | |||
_mkgmtime | 2012, 2013 | 1969/12/31 12:00:00 | 3001/01/01 20:59:59 | 作成値は -43200 〜 32535291599 |
2015, 2017, 2019 | 1969/12/31 12:00:00 | 3001/01/19 21:59:59 | 作成値は -43200 〜 32536850399 | |
mktime | 2012, 2013 | 1970/01/01 00:00:00 | 3001/01/01 07:59:59 | 作成値は 0 〜 32535244799 |
2015, 2017, 2019 | 1970/01/01 00:00:00 | 3001/01/19 07:59:59 | 作成値は 0 〜 32536799999 |
mktime の最小/最大許容値はUTC換算なので、例えば日本のタイムゾーン(UTC+9)で利用する場合、それぞれ9時間ずつ足した値が実際の許容範囲になります。
確認した限りだと、UTCベースの関数とローカルベースの関数でぞれぞれ同じ許容範囲となっているようです。
ただ、どうしてこの値でキャップしているのか、どうしてVC++2015で最大許容値が変更されたのかといった理由は結果だけ見てもわかりませんでした。
個人的には、 gmtime, gmtime_s の time_t 引数値に、最大12時間までとはいえマイナスの値を指定できることに驚きました。