Home » Php » Simulate different server datetimes in PHP

Simulate different server datetimes in PHP

Posted by: admin July 12, 2020 Leave a comment

Questions:

Is it possible to make a PHP application think that the server datetime is offset by a large configurable amount (like 6 months ago, or 6 months from now)?

Background:
We have a web application that deals with sporting events and right now we would like to run it in our development environment in such a way that the web site thinks it is Fall 2009 instead of Summer 2010. That’s because we have great data from last year’s Fall season and this year’s season has not yet started, so testing new features would be easier with scads of real data instead of making up new test data for 2010.

We don’t want to actually change the server’s date and time. The current best option seems to be to change all date() calls in the code to my_date() and then have my_date() add the offset to the actual system date.

It seemed like this feature would be useful in similar situations for others, so I was just curious if there’s an easier way to do it globally through some configuration parameter without modifying code. I did RTM.

How to&Answers:

You could install Runkit on the Development server and redefine all required dateTime functions to return a modified value, e.g.

if(APP_ENV === 'testing') {
    include 'datetime-monkeypatches.php';
}

where datetime-monkeypatches.php would contain your patches to the required functions. This way you wouldnt have to change your actual code. It’s like using an adapter to the original functions and as long as you keep them in that separate file, it stays maintainable.

Another option would be to use http://antecedent.github.io/patchwork

Patchwork is a PHP library that makes it possible to redefine user-defined functions and methods at runtime, loosely replicating the functionality runkit_function_redefine in pure PHP 5.3 code, which, among other things, enables you to replace static and private methods with test doubles.

Answer:

I’ve never tried it, but maybe libfaketime could help, here : it allows one to “fake” the time for a process.

For example, see this article : Changing what time a process thinks it is with libfaketime

But, as said in this ticket of PHPUnit’s Trac, that’s probably something that should be done using your own equivalent of dates functions…

Which means, like you guessed, that the best solution, if you can afford it, would indeed be to use your own my_date() function everywhere.

Answer:

You could use a custom DateTime class:

class My_DateTime extends DateTime
{
    public static $timeModifier = NULL;

    public function __construct($now = 'now', DateTimeZone $timezone = NULL)
    {
        parent::__construct($now);
        if($timezone !== NULL) {
            $this->setTimezone($timezone);
        }
        if(self::$timeModifier !== NULL) {
            $this->modify(self::$timeModifier);
        }
    }
}

In your bootstrap simply set the $timeModifier like this:

if(APP_ENV === 'testing') {
    My_DateTime::$timeModifier = '-6 months';
}

And then you can use it like this from anywhere:

$now = new My_DateTime();
echo $now->format('Y-m-d H:i:s'); // 2010-01-17 16:41:49