Parse a UK date explicitly instead of guessing with strtotime()

Convert a strict DD/MM/YYYY value into a validated PHP date, reject impossible dates and avoid ambiguous separator tricks.

11/12/2026 can mean two different dates. Changing slashes to hyphens may influence PHP's flexible parser, but it still leaves your application's input contract implicit.

State the format you accept

For a form or import that promises DD/MM/YYYY, parse exactly that. This example uses UTC midnight and returns an immutable date object:

<?php
declare(strict_types=1);

function parseUkDate(string $input): DateTimeImmutable
{
    if (!preg_match('/\A[0-9]{2}\/[0-9]{2}\/[0-9]{4}\z/', $input)
        || !checkdate((int) substr($input, 3, 2), (int) substr($input, 0, 2), (int) substr($input, 6, 4))) {
        throw new InvalidArgumentException('Use DD/MM/YYYY.');
    }

    $date = DateTimeImmutable::createFromFormat(
        '!d/m/Y', $input, new DateTimeZone('UTC')
    );
    $errors = DateTimeImmutable::getLastErrors();
    if ($date === false
        || ($errors !== false && ($errors['warning_count'] || $errors['error_count']))
        || $date->format('d/m/Y') !== $input) {
        throw new InvalidArgumentException('Enter a real calendar date.');
    }
    return $date;
}

$date = parseUkDate('11/12/2026');
echo $date->format('Y-m-d'), "\n"; // 2026-12-11

Save it as parse-date.php and run php parse-date.php, or use the function in your application's validation layer. The four-digit year token is uppercase Y. Lowercase y is for a two-digit year and is not interchangeable.

Reject rollover, not just parsing failure

PHP can turn an impossible date such as 31 February into a date in March while reporting a warning. The warning check and format round-trip prevent that silent repair. In newer PHP versions, getLastErrors() returns false when there were no problems, which this code handles.

Return a helpful validation error at the form boundary; do not expose exceptions or silently invent a replacement date. If the value is only a calendar date, store the resulting YYYY-MM-DD string. If it represents an event, choose the event's timezone and time explicitly before turning it into a timestamp.

References: PHP date parsing, parse warnings and errors and strtotime().

Original version18 December 2014

Kept here for reference and earlier links. The updated guide above is the recommended starting point; older code may depend on retired services or different software versions.

By default the PHP function strtotime() will take most date formats, and convert them to a Unix/Epoch timestamp.
However, as versatile as this function is, unfortunately, our planet (Earth) is not quite as succinctly set up.

One main problem is the difference in formatting between UK and USA dates. UK dates are typically formatted: dd/mm/yyyy, whereas USA uses: mm/dd/yyyy.
This becomes particularly confusing for PHP to interpret, as it's not clear whether the following is 11th December or the 12th of November: 11/12/2014

PHP will assume this date 11/12/2014 to be American format, by default. Thus if you actually entered it as a UK date, your data is no longer incorrect.

This problem can easily be solved in a few ways:

Method 1:
The strtotime() function will always assume an American format when the separator of / is used. However if the dash separator (-) is used, it assumes UK format:

<?php 
$date = strtotime(str_replace('/', '-', '11/11/2014')); 
?> 

Method 2: Explicitly set the format and return a DateTime object.

<?php 
$date = date_create_from_format('d/m/y', '27/05/1990'); 
?>

Method 3: Use a string operation to re-format:

<?php
$date = "31/12/2014";
$bits = explode('/',$date);
$date = $bits[1].'/'.$bits[0].'/'.$bits[2];
$date = strtotime($date);
?>

Method 1 should be the easiest solution for most uses, with method 2 being preferable if you want to return a DateTime object that can be better to work with if you need to do further adjustments.
Method 3 is the least preferred method but can be useful if your date format will need slightly more custom handling and manipulation before being converted to the date string format.

Keep exploring

A couple more useful notes.