如何验证ISO 8601日期字符串(例如:2011-10-02T23:25:42Z)。
我知道ISO 8601日期有几种可能的表示形式,但我只想验证上面给出的格式。
谢谢!
答案 0 :(得分:15)
这对我有用,它使用正则表达式来确保日期是您想要的格式,然后尝试解析日期并重新创建它以确保输出与输入匹配:
<?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来确保月份日和年份也有效。
答案 1 :(得分:13)
编辑到目前为止,最简单的方法是尝试使用字符串创建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
}
答案 2 :(得分:10)
我想分享我的轻量级解决方案。这不是理想的,但可能对某人有帮助。
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!强>
某些有效的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!
答案 3 :(得分: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)?)?)?)?$
我认为这并不能完全回答你的问题,因为它会匹配任何有效的ISO 8601日期,但如果这样就好了,那么这种方法就完美了。
答案 4 :(得分:3)
这是我使用的功能。它类似于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;
}
}
答案 5 :(得分:0)
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'));
}