验证 ISO 8601 日期字符串

发布于 2024-12-13 08:46:02 字数 107 浏览 0 评论 0原文

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

我知道 ISO 8601 日期有几种可能的表示形式,但我只对验证上面作为示例给出的格式感兴趣。

How do you validate ISO 8601 date string (ex: 2011-10-02T23:25:42Z).

I know that there are several possible representations of ISO 8601 dates, but I'm only interested in validating the format I gave as an example above.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

浅浅 2024-12-20 08:46:02

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

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!

I want to share my lightweight solution. It is not ideal, but might be helpful for someone.

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;
}

Atention!

Some valid ISO8601 dates will fail Look at the list below

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!
×纯※雪 2024-12-20 08:46:02

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

<?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 以确保月日和年份也有效。

This worked for me, it uses a regular expression to make sure the date is in the format you want, and then tries to parse the date and recreate it to make sure the output matches the input:

<?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;
    }
}

You could expand further to use checkdate to make sure the month day and year are valid as well.

寄意 2024-12-20 08:46:02

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

$dt = new DateTime($dateTimeString);

如果 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
}

Edit: By far the easiest method is to simply try to create a DateTime object using the string, eg

$dt = new DateTime($dateTimeString);

If the DateTime constructor cannot parse the string, it will throw an exception, eg

DateTime::__construct(): Failed to parse time string (2011-10-02T23:25:72Z) at position 18 (2): Unexpected character

Note that if you leave off the time zone designator, it will use the configured default timezone.

Second easiest method is to use a regular expression. Something like this aught to cover it

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
}
相对绾红妆 2024-12-20 08:46:02

请参阅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 日期,但如果没问题的话,那么它就可以完美工作。

See http://www.pelagodesign.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/. It gives this regex to use:

^([\+-]?\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)?)?)?)?$

I suppose this does not answer your question exactly, since it will match any valid ISO 8601 date, but if that is alright then this works perfectly.

第七度阳光i 2024-12-20 08:46:02

这是我使用的功能。它类似于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;
    }
}

This is the function I use. It is similar to the answer of drew010 but works also for timestamps ending with "+01:00" or "-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;
    }
}
樱&纷飞 2024-12-20 08:46:02

Carbon 很好地处理了这部分,

use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
...
/** @test */
public function checking_iso8601_date()
{
    $this->expectException(InvalidFormatException::class);
    Carbon::createFromFormat('c', '2021-05-11 20:03:45+02:00');

    $this->assertInstanceOf(Carbon::class, Carbon::createFromFormat('c', '2021-05-11T20:03:45+02:00'));
}

您也可以对 DateTime 做同样的事情

use DateTime;
...
/** @test */
public function checking_iso8601_date()
{
    $this->assertInstanceOf(DateTime::class, DateTime::createFromFormat('Y-m-d\TH:i:sP', '2021-05-11T20:03:45+02:00'));
    $this->assertFalse(DateTime::createFromFormat('Y-m-d\TH:i:sP', '2021-05-11 20:03:45+02:00'));
}

Carbon is handling this part really well

use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
...
/** @test */
public function checking_iso8601_date()
{
    $this->expectException(InvalidFormatException::class);
    Carbon::createFromFormat('c', '2021-05-11 20:03:45+02:00');

    $this->assertInstanceOf(Carbon::class, Carbon::createFromFormat('c', '2021-05-11T20:03:45+02:00'));
}

You may do the same with DateTime

use DateTime;
...
/** @test */
public function checking_iso8601_date()
{
    $this->assertInstanceOf(DateTime::class, DateTime::createFromFormat('Y-m-d\TH:i:sP', '2021-05-11T20:03:45+02:00'));
    $this->assertFalse(DateTime::createFromFormat('Y-m-d\TH:i:sP', '2021-05-11 20:03:45+02:00'));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文