PHPで作成したWEBアプリで未来や過去の日時に変更して動作確認したいことは結構あります。 dateコマンドを使う †よく使われるのはdateコマンドでサーバの時間を変更してしまうことでしょう。 現在日時を確認 # date Fri Nov 3 01:24:56 UTC 2023 2023年11月4日12時に変更 # date --set "2023/11/04 12:00:00" Sat Nov 4 12:00:00 UTC 2023 確認 # date Sat Nov 4 12:00:03 UTC 2023 戻す # ntpdate -s -b ntp.jst.mfeed.ad.jp Docker環境で operation not permitted のエラーが出る場合は docker-compose.yml へ設定を追加します。 services: app: # これを追加 privileged: true ntpdate が無い場合は入れます。 # apt install ntpdate Carbonを使う †setTestNow が使えます。 $knownDate = Carbon::create(2001, 5, 21, 12); // create testing date Carbon::setTestNow($knownDate); // set the mock (of course this could be a real mock object) echo Carbon::getTestNow(); // 2001-05-21 12:00:00 echo Carbon::now(); // 2001-05-21 12:00:00 echo new Carbon(); // 2001-05-21 12:00:00 echo Carbon::parse(); // 2001-05-21 12:00:00 echo new Carbon('now'); // 2001-05-21 12:00:00 echo Carbon::parse('now'); // 2001-05-21 12:00:00 echo Carbon::create(2001, 4, 21, 12)->diffForHumans(); // 1 month ago var_dump(Carbon::hasTestNow()); // bool(true) Carbon::setTestNow(); // clear the mock var_dump(Carbon::hasTestNow()); // bool(false) echo Carbon::now(); // 2023-10-03 07:59:07 // Instead of mock and clear mock, you also can use withTestNow(): Carbon::withTestNow('2010-09-15', static function () { echo Carbon::now(); }); // 2010-09-15 00:00:00 https://carbon.nesbot.com/docs/#api-testing Chronosを使う †Carbonと同様に setTestNow が使えます。 Chronos::setTestNow(new Chronos('1975-12-25 00:00:00')); $time = new Chronos(); // 1975-12-25 00:00:00 $time = new Chronos('1 hour ago'); // 1975-12-24 23:00:00 https://book.cakephp.org/chronos/2/ja/index.html#id11 php-timecopを使う †PHPの拡張モジュールを入れる方法です。 PECLが用意されていますが、PHP7.2までしか対応していません。 Gitもありますが、同様メンテナンスが止まっています。 さらに調べると本家からforkして2023年11月時点でPHP8.2まで対応しているのでこれを使います。 インストール †# cd /usr/local/src/ # git clone https://github.com/kiddivouchers/php-timecop.git # cd php-timecop # phpize # ./configure # make # make install # vi /usr/local/etc/php/php.ini extension=timecop.so WEBサーバを再起動して timecop が含まれているか確認します。 # php -m 使用方法 †使える関数は3つです。 if (function_exists('timecop_freeze')) { $unixtimestamp = (new \DateTime('2023-11-04 12:00:00'))->format('U'); // 日時を固定 timecop_freeze($unixtimestamp); echo (new \DateTime())->format('Y-m-d H:i:s').'<br>'; echo date('Y-m-d H:i:s').'<br>'; // 日時へ変更 timecop_travel($unixtimestamp); echo (new \DateTime())->format('Y-m-d H:i:s').'<br>'; echo date('Y-m-d H:i:s').'<br>'; sleep(10); echo (new \DateTime())->format('Y-m-d H:i:s').'<br>'; echo date('Y-m-d H:i:s').'<br>'; // 日時を戻す timecop_return(); } 結果 2023-11-04 12:00:00 2023-11-04 12:00:00 2023-11-04 12:00:00 2023-11-04 12:00:00 2023-11-04 12:00:10 2023-11-04 12:00:10 |