PHP: Adding time and comparing DateTime objects

I was coding a web app’s “password reset” functionality and I wanted to ensure that the reset link sent to a user’s email address expired after two hours.

I didn’t find any simple explanations of manipulating DateTime objects and then comparing them so I thought I would write a quick ‘how to’ on it in case it helps someone else understand how to get it working.

  1. When the user requested a password reset a database record is generated with a created_at timestamp.
  2. When the user clicks on the link I need to compare the time now against the database record and make sure it’s less than two hours old.

Fortunately using PHP’s DateTime object it’s quite simple to achieve. My approach was to take the database record, add 2 hours to it, and then check if ‘now’ is greater or less than the new DateTime object.


// First get the current time when the visitor requests the reset page from the server
$now = new DateTime();

// Next get the created_at date of the reset key
$reset_key_date = new DateTime($user->reset->created_at);

// Next add two hours to the reset key creation time
$reset_key_date->add(new DateInterval('PT2H'));

// if $now is greater than the reset key date (+2 hours), return error etc
if ($now > $reset_key_date)
{
	// You're too late! Try again!
}

// Otherwise continue on and allow the user to reset their password.

If you’re having trouble getting the DateTime from your database you may need to use createDateFromFormat, but I’ve found DateTime to be pretty good at interpreting strings and certainly if you’re pulling in a DATE_RFC2822 from a MySQL database it will most definitely get it right!

Comments

  • Donncha

    I don’t think I’ve ever used the DateTime class. I would have converted to a Unix timestamp (strtotime) and added 2 hours worth of seconds (7200) if I was going to do something similar but that’s clearer and more readable.

    • I’ve been trying to migrate to the newer classes and stay in the habit of OO style. The DateTime class has taken a little bit of getting used to, but it’s proving very helpful.

      I mainly started to use it when I came across the IntlDateFormatter class which allows correct handling of date formatting based on locale.

      Eg:

      $i18n_date = new IntlDateFormatter( $locale, IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, Session::get(‘timezone’),IntlDateFormatter::GREGORIAN, ‘d MMM yyyy’);

      return $i18n_date->format($timestamp);