#author("2023-11-03T01:56:00+00:00","","")
#author("2023-11-03T02:07:37+00:00","","")
[[PHPめも]]

PHPで作成したWEBアプリで未来や過去の日時に変更して動作確認したいことは結構あります。~
いくつかやり方はあります。

#contents

*dateコマンドを使う [#se277347]

よく使われるのはdateコマンドでサーバの時間を変更してしまうことでしょう。~
ただ他のWEBアプリに影響が出たり、PHP-FPMのキャッシュが更新されなかったりと何かと悪影響が出るのでおすすめしないです。

現在日時を確認
 # 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を使う [#sbaa587d]

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を使う [#x582db0a]

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を使う [#ub9df89e]

PHPの拡張モジュールを入れる方法です。~
個人的におすすめ。

PECLが用意されていますが、PHP7.2までしか対応していません。~
https://pecl.php.net/package/timecop

Gitもありますが、同様メンテナンスが止まっています。~
https://github.com/hnw/php-timecop

さらに調べると本家からforkして2023年11月時点でPHP8.2まで対応しているのでこれを使います。~
https://github.com/kiddivouchers/php-timecop

**インストールから使用方法まで [#z579fcaf]
**インストール [#g4168f1e]

 # 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

**使用方法 [#m41c3535]

使える関数は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

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS