ひとまず現在時刻との話。
まとめ
- Unix タイムスタンプをそのまま
DateTime
の__construct
に渡してもエラーとなる。 -
new DateTime('@' . time())
と頭に@
を付けると書式が認められDateTimeインスタンスが得られる。 - ただし、
new DateTime('@' . time())
ではマシンのタイムゾーンが反映されず、第二引数にタイムゾーンを指定しても効かない。 - インスタンスに対してタイムゾーンを指定する一手間が必要。
-
new DateTime()
ではタイムゾーンは適応されている(ex:Asia/Tokyo
)ので、タイムゾーンを意識しないと9時間ずれる。 - PHPで時刻を取る関数の返り値はUnix タイムスタンプが多い1
- 忘れやすいタイムゾーンを考慮するぐらいならば、もうUnix タイムスタンプを扱う必要が出た時点で無理に
DateTime
に変換しなくてもいいのではないか
(PHPマニュアルの表記に倣いWikiでのUnix時間をUnix タイムスタンプと呼んでいます)
Unix タイムスタンプでDateTime
を作れなくていつも困るので見つけた記念にメモしようと思ったら、そもそもあまりよくなさそうという話。
参考
- DateTimeオブジェクトにUNIXタイムスタンプとタイムゾーンを指定した時の挙動に関する備忘録 - Qiita
- DateTimeクラスで日付文字列とUNIX時間(タイムスタンプ)を相互変換するときのまとめ - Qiita
話としては参考記事で終わりだが、ではどうするのがいいのかと悩む。
検証環境
- PHP 5.4
<?php
$tz = new DateTimeZone('Asia/Tokyo');
echo ((new DateTime())->format('Y-m-d H:i:s')) . "\n";
echo ((new DateTime('@' . time()))->format('Y-m-d H:i:s')) . "\n";
echo ((new DateTime('@' . time(), $tz))->format('Y-m-d H:i:s')) . "\n";
echo ((new DateTime('@' . time()))->setTimeZone($tz)->format('Y-m-d H:i:s')) . "\n";
2018-03-01 14:48:18
2018-03-01 05:48:18
2018-03-01 05:48:18
2018-03-01 14:48:18
file(a,m,c)time()
はすべてUnix タイムスタンプで返すので、
ファイルがどれぐらい古いか=現在時刻との比較・差秒算出ならnew DateTime()
よりtime()
で計算したほうが心配がない。のでは。
(new DateTime('@' . time()))->setTimeZone(new DateTimeZone())
では理由がコードから読み取れず、似たことをするときに
-
setTimeZone()
をつけわすれる - タイムゾーンは自動で合わせられるはずと勘違いして取り除くリファクタリング
- 第二引数でタイムゾーン指定できるのでこの書き方は冗長とリファクタリング
のどれかを自分なら踏み抜きそう。2
ただなんでもUnix タイムスタンプで処理しろというわけではなく、
文字列で日付が来たらstrtotime()
よりDateTime
の方がいいと思っている。
あくまでどれか一つ、Unix タイムスタンプでしかとれない時刻が出てきたら、そっちに合わせたほうがいいんじゃないかなーという所感。
この経緯自体覚えることが難しそう…