概要
2038年問題というのがあるらしい。
多くのケースで、timestampが内部的には32ビットの符合付き整数で、2038年1月19日3時14分7秒(UTC)
にその上限を迎える。
MySQLも例外ではなくtimestamp型を使っている場合、これにハマることになるとのこと。
LaravelのIlluminate\Database\Schema\Blueprint::timestamps
もtimestamp型を使ってるので、Laravel使ってる人にもふつうに影響デカそうです。
対策
対策としては
- Datetime型を使う
- 整数型を使う
という方法があるみたいです。
1. Datetime型を使う場合の注意点
DATETIME型は、タイムゾーンの影響を受けません。 そのため、タイムゾーンがUTC→JSTに切り替えても同じ値が入り、日付データが絶対値とならない可能性があります
https://qiita.com/juve_534/items/a9f9f72d49f8817951e8
2. 整数方を使う場合の注意点
ちなみに、2. の解決法とるときに何も考えずintとか使っても何も変わらないから気を付ける。intも32ビットの符合付き整数だから。unsigned int にすれば寿命が68年伸びます。bigintegerにすれば、人類が生きているうちは大丈夫でしょう。
ざっと計算してみると…(閏年を考慮していないので日数ずれてる)
# 検証 integer_max = 2147483647 unsignedinteger_max = 4294967295 biginteger_max = 9223372036854775807 unsignedbiginteger_max = 18446744073709551615 def to_datetime(unixtime): r = [0] * 5 r[0] = year = unixtime // (60 * 60 * 24 * 365) r[1] = day = ( unixtime % (60 * 60 * 24 * 365)) // (60 * 60 * 24) r[2] = hour = (( unixtime % (60 * 60 * 24 * 365)) % (60 * 60 * 24)) // (60 * 60) r[3] = minute = (((unixtime % (60 * 60 * 24 * 365)) % (60 * 60 * 24)) % (60 * 60)) // 60 r[4] = second = (((unixtime % (60 * 60 * 24 * 365)) % (60 * 60 * 24)) % (60 * 60)) % 60 return tuple(r) print('interger: %d年%d日%d時%d分%d秒' % to_datetime(integer_max)) print('unsignedinterger: %d年%d日%d時%d分%d秒' % to_datetime(unsignedinteger_max)) print('biginterger: %d年%d日%d時%d分%d秒' % to_datetime(biginteger_max)) print('unsignedbiginterger: %d年%d日%d時%d分%d秒' % to_datetime(unsignedbiginteger_max))
結果
interger: 68年35日3時14分7秒 unsignedinterger: 136年70日6時28分15秒 biginterger: 292471208677年195日15時30分7秒 unsignedbiginterger: 584942417355年26日7時0分15秒
参考記事
MySQLで timestamp型 を使うのはNG!2038年問題の対処法 | PisukeCode - Web開発まとめ
MySQLのtimestamp型に起きる2038年問題 - Qiita
補足
ちなみにCookieも同じ問題を抱えているらしいですね。