PHP DateTime принимает недопустимую дату

У меня возникли проблемы с использованием класса PHP DateTime и, более конкретно, DateTime::createFromFormat().

Я получаю дату из строки, а затем пытаюсь инициализировать объект DateTime, используя DateTime::createFromFormat(). Но когда я даю этой функции дату, которая не может существовать, она все еще работает, возвращая мне действительный объект DateTime с допустимой датой , который не является датой, которую я дал ей.

Пример кода:

$badDate = '2010-13-03';
$date = DateTime::createFromFormat('Y-m-d', $badDate);

var_dump($date);

/*
object(DateTime)#284 (3) {
["date"]=>
string(19) "2011-01-03 10:01:20"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
*/

Любые идеи? Мне действительно нужен способ проверить правильность даты.

Спасибо.

Изменить:

Я только что нашел, почему, см. мой ответ.

Ответ 1

DateTime::createFromFormat не генерирует исключение/возвращает false, когда данная дата невозможна. Он пытается угадать ожидаемую дату.

Если вы дадите ему '2010-01-32' (как в Januar, 32), он вернет объект DateTime, содержащий Februar, 1st (Januar 31th + 1 day). Должен быть логичным... каким-то странным скрученным способом.

Чтобы проверить правильность, вы должны проверить DateTime::getLastErrors(), который содержит предупреждение, например, для моего случая:

array(4) {
  ["warning_count"]=>
  int(1)
  ["warnings"]=>
  array(1) {
    [10]=>
    string(27) "The parsed date was invalid"
  }
  ["error_count"]=>
  int(0)
  ["errors"]=>
  array(0) {
  }
}

Это похоже на временную метку UNIX, которую PHP вычисляет на основе года, месяца и даты, которые вы даете (даже если дата недействительна).

Ответ 2

Вы должны использовать DateTime::getLastErrors(), который будет содержать ошибку The parsed date was invalid.

$badDate = '2010-13-03';
$date = DateTime::createFromFormat('Y-m-d', $badDate);
if( DateTime::getLastErrors()['warning_count'] > 0 ){
 //not a correct date
}else{
 //correct date
 print $date->format('Y-m-d');
}

Ответ 3

Я нашел пример, где проверка на основе DateTime::getLastErrors() завершится неудачно, поэтому лучшим решением было бы сравнить введенную дату с сгенерированной датой.

код:

function validateDate($date, $format = 'Y-m-d')
{
    $dt = DateTime::createFromFormat($format, $date);
    return $dt && $dt->format($format) == $date;
}

Пример использования:

var_dump(validateDate('2012-02-28')); # true
var_dump(validateDate('2012-02-30')); # false

# you can validate and date/time format
var_dump(validateDate('14:50', 'H:i')); # true
var_dump(validateDate('14:99', 'H:i')); # false

# this is the example where validation with `DateTime::getLastErrors()` will fail
var_dump(validateDate('Tue, 28 Feb 2012 12:12:12 +0200', DateTime::RSS)); # true
var_dump(validateDate('Tue, 27 Feb 2012 12:12:12 +0200', DateTime::RSS)); # false

Ответ 4

Найдите checkdate() в документации php. Это поможет вам:)

Ответ 5

Вы можете сделать это:

DateTime::getLastErrors()

Ответ 6

изменить

$date = DateTime::createFromFormat('Y-m-d', $badDate);

в

$date = DateTime::createFromFormat('Y-d-m', $badDate);

Ваш данный формат неверен, вы правильно перемешали дни и месяцы...

Чтобы понять, что находится за магическим расчетом дат, читайте эту очень хорошую статью Дерика Ретанса и все комментарии;)