PHP验证ISO 8601日期字符串

tit*_*tel 18 php validation iso8601

如何验证ISO 8601日期字符串(例如:2011-10-02T23:25:42Z).

我知道ISO 8601日期有几种可能的表示形式,但我只想验证上面给出的格式作为例子.

谢谢!

dre*_*010 17

这对我有用,它使用正则表达式来确保日期是您想要的格式,然后尝试解析日期并重新创建它以确保输出与输入匹配:

<?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;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以进一步扩展以使用checkdate来确保月份日和年份也有效.

  • a)不要使用不区分大小写的标志; `T`和`Z`是唯一适用的字母字符,应该都是大写的.b)`Z`不是唯一有效的时区指示符.见http://en.wikipedia.org/wiki/ISO_8601#Dates (3认同)
  • 你还应该在日期字符串前面允许一个可选的`+`或`-`(http://en.wikipedia.org/wiki/ISO_8601#Years).可能一个`([+ | - ]?)`就足够了 (2认同)

Phi*_*hil 15

编辑:到目前为止,最简单的方法是简单地尝试DateTime使用字符串创建对象,例如

$dt = new DateTime($dateTimeString);
Run Code Online (Sandbox Code Playgroud)

如果DateTime构造函数无法解析字符串,则会抛出异常,例如

DateTime :: __ construct():无法解析位置18(2)处的时间字符串(2011-10-02T23:25:72Z):意外字符

请注意,如果您不使用时区指示符,它将使用配置的默认时区.

第二种最简单的方法是使用正则表达式.这样的东西可以覆盖它

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
}
Run Code Online (Sandbox Code Playgroud)

  • @Phil好,如果你想检查它是否是一个有效的iso日期,然后让它允许其他非iso的日期格式使它不是iso格式的验证. (14认同)
  • 不错的想法,但DateTime构造函数不限于ISO 8601输入. (9认同)

Jek*_*kis 11

我想分享我的轻量级解决方案.这不是理想的,但可能对某人有帮助.

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;
}
Run Code Online (Sandbox Code Playgroud)

Atention!

一些有效的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!
Run Code Online (Sandbox Code Playgroud)


jli*_*jli 5

请参阅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)?)?)?)?$
Run Code Online (Sandbox Code Playgroud)

我认为这不能完全回答你的问题,因为它会匹配任何有效的ISO 8601日期,但如果这样就好了,那么这种方法非常有效.


小智 5

这是我使用的功能。它类似于draw010的答案,但也适用于以“+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;
    }
}
Run Code Online (Sandbox Code Playgroud)