Cowburn — Find me on GitHub and StackOverflow.

Parsing Dates with DateTime

This post comes on the back of a number of forum posts I've seen floating around where the Original Poster (OP) asks a question along the lines of, "I have a date in dd/mm/yyy format, how can I work with it?"

The problem is that the most common way of parsing strings into a more usable format (Unix timestamp) is to use strtotime(). However, this function does not like dd/mm/yyyy formatted strings and will at best parse the string as mm/dd/yyyy and at worst return FALSE (if it could not parse the date string as mm/dd/yyyy).

Quick workaround

One quick thing that works, and I've advocated in forum posts before, is to provide a date string in the format dd-mm-yyyy. Note that the date parts are in the same order, just the separator has changed from a forward slash (/) to a hyphen (-). A date formatted in this way will be happily parsed by strtotime(). For example:

date_default_timezone_set('UTC');
$date = '14/06/2009';                 // dd/mm/yyyy
$date = str_replace('/', '-', $date); // dd-mm-yyyy
echo date('r', strtotime($date));
// Sun, 14 Jun 2009 00:00:00 +0000

Using DateTime

As of PHP 5.2.0 (and experimentally in 5.1.x) we have also had the ability to play with dates and times using the built-in DateTime extension (Aside: the date_default_timezone_set function used above comes from this extension). To repeat the above but in DateTime form:

$date = '14/06/2009';                 // dd/mm/yyyy
$date = str_replace('/', '-', $date); // dd-mm-yyyy
$date = new DateTime($date, new DateTimeZone('UTC'));
echo $date->format('r');
// Sun, 14 Jun 2009 00:00:00 +0000

Help Coming!

I'm sure that you'll agree, the above is hardly a perfect solution to the problem (but is a sufficient workaround for now). However help is at hand. As of PHP 5.3.0 we will be able to make use of a new static method on the DateTime class. This method is DateTime::createFromFormat() which requires two arguments; a string specifying the format which the date string has (as used by the date() function), and the date string itself (there is also a third, optional, argument for the timezone to be used).

An example of its use, analogous to the snippets above, would be:

$date = DateTime::createFromFormat('d/m/Y', '14/06/2009', new DateTimeZone('UTC'));
$date->setTime(0,0,0);
echo $date->format('r');
// Sun, 14 Jun 2009 00:00:00 +0000

Aside: For my installation (PHP 5.3.0RC3) this method does not parse the date string as midnight, as the other code snippets do, but will use current time! This is why the setTime() method (available as of 5.2.0) is used, to force the time to be midnight (arguments are hour, minute, second). Edit: One could instead use the ! within the format string like !d/m/Y, since the time portion is missing it will substitute the Unix epoch's time (midnight) in its place. See the manual for details of !.

Just to wrap things up, the DateTime::createFromFormat() should help considerably towards parsing previously ambiguous date strings into forms that can be manipulated and at least will get around the string manipulation being offered as a solution right now. If you're still stuck playing around with the date string, at least you know that dd-mm-yyyy will be parsed as you want.