Как вы проверяете строку даты ISO 8601 (например: 2011-10-02T23:25:42Z).
Я знаю, что существует несколько возможных представлений дат ISO 8601, но меня интересует только проверка формата, который я привел в качестве примера выше.
Спасибо!
Как вы проверяете строку даты ISO 8601 (например: 2011-10-02T23:25:42Z).
Я знаю, что существует несколько возможных представлений дат ISO 8601, но меня интересует только проверка формата, который я привел в качестве примера выше.
Спасибо!
Это сработало для меня, оно использует регулярное выражение, чтобы убедиться, что дата находится в нужном вам формате, а затем пытается проанализировать дату и воссоздать ее, чтобы убедиться, что вывод соответствует вводу:
<?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, чтобы убедиться, что день месяца и год также действительны.
T
и Z
являются единственными применимыми буквенными символами, и оба они должны быть в верхнем регистре. б) Z
— не единственный допустимый указатель часового пояса. См. en.wikipedia.org/wiki/ISO_8601#Dates.
- person Phil; 04.11.2011
+
или -
перед строкой даты (en.wikipedia.org/ wiki/ISO_8601#Годы). наверное ([+|-]?)
будет достаточно
- person Luciano Mammino; 13.09.2014
Редактировать. Самый простой способ — просто попытаться создать объект 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
}
Я хочу поделиться своим легким решением. Это не идеально, но может быть полезно для кого-то.
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!
strtotime($value);
возвращает false
, если $value
не поддается разбору. $date = date(DATE_ISO8601, $timestamp);
с $timestamp = false;
содержит минимальную дату (1970-01-01T01:00:00+0100). Так что этот пример плохой. Не использовать.
- person MrBoolean; 22.02.2016
$value
и будет возвращено false
- person Jekis; 22.02.2016
strtotime
также будет анализировать что-то вроде a day ago
или 2015-01 first
и многое другое. В этот момент эта функция не работает.
- person MrBoolean; 22.02.2016
См. 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, но если это нормально, то это работает отлично.
3401
. Используйте на свой риск.
- person Madhur Bhaiya; 24.04.2021
Это функция, которую я использую. Это похоже на ответ 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;
}
}
Карбон отлично справляется с этой задачей.
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'));
}