Benchmark: strtotime() vs DateTime vs getTimestamp in PHP

Recently I wrote about how one can implement date comparison in PHP. In the article I presented two approaches. Firstly, using the strtotime() method and another with the DateTime class.

Then, in the comments on the german division of this blog, it was pointed out that the strtotime() variant is probably faster. Because I wasn’t sure about this, I decided to make a small performance test and share the results with you in this article.

How did I test the performance?

Since the question aims on strtotime() vs. DateTime, the DateTime class is contrary to the strtotime() function. So because DateTime class offers more functionality, I had first to create the DateTime object and then get the timestamp of it, because the strtotime function gives a timestamp as return value and I wanted to compare the time needed to generate the identical output.

As input I have taken a date without a custom time – say a year, month and day indication. In addition, I tested a third function. What exactly is going on with the getTimestamp () function, I will explain later in the article. The three function calls for my following benchmark look as follows:

//strtotime()
$a=strtotime("2012-05-28");

//DateTime
$date=new DateTime("2012-05-28");
$a = $date->getTimestamp();

//getTimestamp()
$a = getTimestamp("2012-05-28");

How did I measure?

As a reference value I wanted to specify the time in seconds. To measure time, I used the following functions:

//Time prior to the execution of a variant
$startTime = microtime(true);

/***************************
  Run variant / tests
****************************/

//Time after the end of the test
$endTime = microtime(true);
//Period of the test
$elapsedTime = abs($startTime - $endTime);

Each of the functions has been called in a loop for 100000 times while the time was measured. To compensate for fluctuations and measurement inaccuracies, the measurement for each variant was performed 20 times and the mean/average “elapsed time” of 20 measurements was taken. Finally the code for my benchmark looked as follows:

$total = 0;
for ($runs = 0; $runs < 20; $runs++)
{
    $startTime = microtime(true);
    for ($i = 0; $i < 100000; $i++)
    {
        //Execute function / variant
    }
    $endTime = microtime(true);
    $total += abs($startTime - $endTime);
}
$elapsedTime = sprintf("%.4f sec.", ($total/20));

I also have added the following line of code at the beginning of the benchmark scripts to set the correct time zone for the strtotime()-function as well as for the DateTime variant.

date_default_timezone_set("Europe/Berlin");

I have written and run the test code in WebMatrix 2 via its supplied IIS Express Web server. The hardware of the test environment was as follows:

  • Acer Aspire 5740G (Notebook)
  • Intel Core i3 M 330 @ 2.13Ghz
  • 8GB Ram
  • Windows 8 Pro (64-Bit)

What is the result?

The result ended up so as it had already suspected by Christoph. The DateTime variant was behind the strtotime() function. Second place went to the getTimestamp () function. In initial tests, this cut off so good that made it to the first place. Here, however, still lacked some calculations, which have finally catapulted getTimestamp() to second place.

I have summarized the whole thing in two small graphics.

php_date_to_timestamp_benchmark1

php_date_to_timestamp_benchmark_percent

What’s up with the getTimestamp()?

The getTimestamp () function is not an official PHP function, but a small in-house development from me. After doing a few tests with strtotime() – which had out performed the DateTime version, I wanted to see if I myself can create a faster version.

As can be seen from the above graphs, mine function was not quite successful. In initial tests it had indeed worked, but I was made aware in the comments that my getTimestamp() function would not always return the correct values.  After I have added the missing switching between summer and winter time (for our room – in America will be converted on other dates!), my function is now a little bit slower than the strtotime() function.

My getTimestamp function looks like this:

function getTimestamp($timeStr)
{
    $daysInMonth = array(0,31,59,90,120,151,181,212,243,273,304,334);
    $dateArr = explode("-", $timeStr);

    //Add years to the day of the year entered
    $days = ($dateArr[0]-1970) * 365;

    //Add leap years, days
    for ($i = 1972; $i <= $dateArr[0]; $i+=4)
    {
        if (($i%4==0 && $i%100 != 0) || $i%400==0)
            $days++;
    }

    //Days until 31.03. of the year
    $daysTimeswitch = $days + 90;
    //Determine day of the week using MOD 3 . (+3 because 01.01.1970 = Thursday)
    //Pull off day of the week from 31. = last Sunday of the month => Daylight saving time
    $daySummertime = 31 - ((($daysTimeswitch%7) + 3)%7);

    $daysTimeswitch = $days + 304;
    $dayWintertime = 31 - ((($daysTimeswitch%7) + 3)%7);

    if (($dateArr[1] > 3 && $dateArr[1] < 10)
        || ($dateArr[1] == 3 && $dateArr[2] > $daySummertime)
        || ($dateArr[1] == 10 && $dateArr[2] <= $dayWintertime))
    {
         $summerWinterTime = 3600;
    }
    else{
         $summerWinterTime = 0;
    }

    //Pull off leap year day
    $days -= (($dateArr[0]%4==0 &&  $dateArr[0]%100 != 0) ||  $dateArr[0]%400==0) ? ($dateArr[1] > 2) ? 0 : 1 : 0;

    //Add days to months of the current year
    $days += $daysInMonth[$dateArr[1]-1];

    //Add days of the current year
    $days += $dateArr[2] - 1;

    //Pull off 3600 seconds for time shift. (Unix timestamp / UTC)
    return $days * 86400 - 3600 - $summerWinterTime;
}

Anyone who has attentive read the source code of the above function, perhaps wants to scream “Hold on …”. Yes, correctly I have to admit that my function gives correct values only under certain circumstances.  Following requirements must be met:

  • The date must be passed in the form YYYY-MM-DD
  • The date should not be older than the 01/01/1970

The strtotime() function takes also data in other formats and can calculate to a certain extent also timestamps of data before 01/01/1970. Here my function is clearly at a disadvantage and you might be wondering whether the comparison then may be unjustified. However, one must also note that the DateTime class in turn provides greater functionality than the strtotime() function. So this would also be unjustified…

And since in the benchmark it only was about the generation of timestamps from a given date, I think that my function has its right to exist. To be a stickler for details – the Unix timestamp begins on 01/01/1970 and thus my function meets the basic requirements for calculating a Unix timestamp.

Conclusion

Claiming strtotime() is faster than DateTime could be assigned by the test. In addition, I was able to determine that I’m not able to write a faster function than strtotime(). At the beginning of the tests, I thought that if I would limit myself to the minimum, I could write a faster function. Finally, the strtotime() function has a few more  options than my getTimestamp() function and however, it did not succeed.

Ultimately, the choice of method should also always be taken in the context of the project. What format is you input data? Do I perhaps like to calculate more than just the timestamp?

Finally, a question to you – the readers: Have any of you ever tried to write a function that is faster than strtotime()? And if so, which way did you go and what problems did you encounter?

4 Comments

  1. Wow it’s wonderful. Keep update with new blogs.

  2. I like this blog. Thank you for sharing this information.

  3. Someonesays:

    The custom getTimestamp()-function is completely unnecessary and therefore the benchmark misleading. Datetime can provide a timestamp by calling the built-in method “format” with the parameter “U.”

    $time = new DateTime(“2012-05-28”);
    echo $time->format(“U”);

  4. Hi there:

    For the record, I ran the test (php 7.2 i7, 64bits)

    and it is my results: (with average, minimum and maximum)

    strtotime avg: 0.1621 min:0.1450 max:0.2015
    DateTime avg: 0.2334 min:0.2128 max:0.2803
    DateTime::createFromFormat avg: 0.2320 min:0.2062 max:0.2798
    getTimestamp avg: 0.2104 min:0.1857 max:0.2694

    I added createFromFormat:
    $date=DateTime::createFromFormat(‘Y-m-d’, ‘2012-05-28’)->getTimestamp();

    And it is close to creating a DateTime() object

Leave a comment

Please be polite. We appreciate that. Your email address will not be published and required fields are marked