2038年問題に対応する
MySQLは2038年問題を抱えています。
協定世界時における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秒、閏秒は考慮していない)を過ぎると、この値がオーバーフローし、負と扱われる[注釈 2]ため、もし時刻を正しく扱えていることを前提としたコードがあれば、誤動作する。
つまり、2038-01-19 12:14:07
以降の日時だと0000-00-00 00:00:00
になる問題です。
デフォルトのままだと、いつか詰みますね
この対応策としては、下記の二つになります。
- DATETIME型を利用する
- INT型でUNIXタイムスタンプを管理する
DATETIME型は指定するだけなので、簡単ですよね
ですが今回は、INT型のUNIXタイムスタンプで管理したいと思います。
UNIXタイムスタンプで管理する。
なぜ採用するかというと、INT型の方が早いためです。
unixタイムスタンプは2147483647
のように数字で日時を管理します。
数字だけで文字を入れていない分高速で処理できます。
また、どの国の日時にも変換可能なのでグローバルに対応したいときにも便利です。
でもどうやってやるか?って日本の記事だとあんまり見かけないので、まとめたいと思います
テーブル作成時
unixタイムスタンプは2147483647
のように数字で日時を管理します。
migrationファイルを生成時、デフォルトだと下記のtimestamps()が追加されています。
$table->timestamps();
この箇所を削除し、代わりにint型で対応します。
$table->integer('created_at');
$table->integer('updated_at');
モデルの設定を変更する
int型にしましたが、デフォルトでは通常のタイムスタンプのままです。
そのため、保存形式を変えてあげます。
protected $dateFormat = 'U';
モデルに上記を追加して、保存フォーマットを変更します。
Unixの’U’を追加するだけで大丈夫です。
protected function getDateFormat()
{
return 'U';
}
上記のやり方でオーバーライドする方法もあるようです。
基本的には$dateFormatを変更するやり方で問題ないでしょう
これだけでunixタイムスタンプ形式で保存されます。
変換する方法
通常のタイムスタンプからunix型に変更するときも同じです。
$start = new Carbon('2022-01-01 00:00:00');
$startUnix = $start->format('U');
逆にunix型から変換するときは、createFromTimestamp
で生成します
Carbon::createFromTimestamp($post->created_at)
検索する際
日付をintで表現をしているため、検索する際も形式を合わせます。
where('created_at', '>', Carbon::now()->getTimestamp())
このようにUnix タイムスタンプを取得を取得して検索をします。
終わりに
考えなしにデフォルトのままサービスを運用すると、重いし、2038問題あるしで 後々困ります
なので、新規案件の際は気をつけていきましょう!
検索負荷も軽減できるので、積極的に採用した方がよいです。
コメント