PHP проверяет строку даты ISO 8601 - PullRequest
18 голосов
/ 04 ноября 2011

Как вы проверяете строку даты ISO 8601 (например, 2011-10-02T23: 25: 42Z).

Я знаю, что существует несколько возможных представлений дат ISO 8601, но меня интересует тольков проверке формата, который я привел в качестве примера выше.

Спасибо!

Ответы [ 5 ]

16 голосов
/ 04 ноября 2011

Это сработало для меня, оно использует регулярное выражение, чтобы убедиться, что дата находится в нужном вам формате, а затем пытается проанализировать дату и воссоздать ее, чтобы убедиться, что выходные данные соответствуют вводу:

<?php

$date = '2011-10-02T23:25:42Z';
var_dump(validateDate($date));

$date = '2011-17-17T23:25:42Z';
var_dump(validateDate($date));

function validateDate($date)
{
    if (preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/', $date, $parts) == true) {
        $time = gmmktime($parts[4], $parts[5], $parts[6], $parts[2], $parts[3], $parts[1]);

        $input_time = strtotime($date);
        if ($input_time === false) return false;

        return $input_time == $time;
    } else {
        return false;
    }
}

Вы можете расширить список, используя checkdate , чтобы убедиться, что день и год месяца также действительны.

13 голосов
/ 04 ноября 2011

Редактировать: На сегодняшний день самый простой способ - просто попытаться создать объект DateTime с использованием строки, например

$dt = new DateTime($dateTimeString);

Если конструктор DateTime не может проанализировать строку, он выдаст исключение, например,

DateTime :: __ construct (): Не удалось проанализировать строку времени (2011-10-02T23: 25: 72Z) в позиции 18 (2): неожиданный символ

Обратите внимание, что если вы не укажете указатель часового пояса, он будет использовать настроенный часовой пояс по умолчанию.

Второй самый простой способ - использовать регулярное выражение. Нечто подобное должно покрыть это

if (preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(Z|(\+|-)\d{2}(:?\d{2})?)$/', $dateString, $parts)) {
    // valid string format, can now check parts

    $year  = $parts[1];
    $month = $parts[2];
    $day   = $parts[3];

    // etc
}
10 голосов
/ 21 января 2014

Я хочу поделиться своим легким решением.Это не идеально, но может быть полезно для кого-то.

function validISO8601Date($value)
{
    if (!is_string($value)) {
        return false;
    }

    $dateTime = \DateTime::createFromFormat(\DateTime::ISO8601, $value);

    if ($dateTime) {
        return $dateTime->format(\DateTime::ISO8601) === $value;
    }

    return false;
}

Внимание!

Некоторые действительные даты ISO8601 не пройдут список ниже

NOT VALID  --> '' // Correct
NOT VALID  --> 'string' // Correct
VALID      --> '2000-01-01T01:00:00+1200' // This is the only format function returns as valid
NOT VALID  --> '2015-01 first' // Correct
NOT VALID  --> '2000-01-01T01:00:00Z' // Must be valid!
NOT VALID  --> '2000-01-01T01:00:00+01' // Must be valid!
5 голосов
/ 04 ноября 2011

См. http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/.. Это дает регулярное выражение для использования:

^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$

Я полагаю, что это не дает точного ответа на ваш вопрос, так как оно будет соответствовать любой действительной дате ISO 8601, но если этоХорошо, тогда это работает отлично.

3 голосов
/ 21 января 2014

Это функция, которую я использую. Он аналогичен ответу drew010, но работает и для отметок времени, заканчивающихся на «+01: 00» или «-01: 00».

function isTimestampIsoValid($timestamp)
{
    if (preg_match('/^'.
            '(\d{4})-(\d{2})-(\d{2})T'. // YYYY-MM-DDT ex: 2014-01-01T
            '(\d{2}):(\d{2}):(\d{2})'.  // HH-MM-SS  ex: 17:00:00
            '(Z|((-|\+)\d{2}:\d{2}))'.  // Z or +01:00 or -01:00
            '$/', $timestamp, $parts) == true)
    {
        try {
            new \DateTime($timestamp);
            return true;
        }
        catch ( \Exception $e)
        {
            return false;
        }
    } else {
        return false;
    }
}
...