tags:

views:

30

answers:

3

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 RTFM.

A: 

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.

Pascal MARTIN
Unfortunately this is on a managed server so we don't have root access on that particular box. Very interesting, though!
royappa
+1  A: 

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
Gordon
Unfortunately we're using the native date() call in a bunch of places.
royappa
@royappa well, yes. You would have to replace all native calls. Just like you would when using a custom my_date function.
Gordon
Yes, understood. Thanks.
royappa
A: 

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.

Gordon
This might work for us, will investigate. Thanks!
royappa