понедельник, 6 апреля 2020 г.

Неявное поведение DateTime::createFromFormat

Данный пост есть результат недавнего обсуждения в одном из php-каналов некоторого странного (как кажется изначально) поведения функции DateTime::createFromFormat.

Рассмотрим простейший код, надо отметить, что исследуемое поведение отмечается только 31-го числа каждого месяца (ну и плюс 29-30 для февраля):

$months = [1, 2, 3, 4];

foreach ($months as $month) {
    $dt = '2019-' . $month;
    echo $dt . ': ' . (\DateTime::createFromFormat('Y-m', $dt))->format('Y-m-d') . PHP_EOL;
}


Обратите внимание, что при создании объекта не указывается день. Так как день не указан, то разумно предположить (это же подтверждается в комментариях), что php берет в качестве дня текущий день запуска скрипта из системных настроек.

Таким образом, запуская скрипт, например, 31-го мая, получим такой вывод:

// ожидаемо, в январе есть 31 число
2019-1: 31.01.2019
// в феврале-2019 нет 29 (и 30 и 31) числа, потому 31-му февраля
// соответствует третье марта (а 29-му февраля - первое марта)
2019-2: 03.03.2019
// ожидаемо, в марте есть 31 число
2019-3: 31.03.2019
// в апреле нет 31 числа, и следующим после 30 апреля идет 1 мая
2019-4: 01.05.2019


Как видим, происходит не то, что ожидается, хотя в другие дни - всё работает нормально, и даже имеющиеся тесты будут проходить.

Можно, конечно, рассуждать о том, что раз день не указан, то может надо кидать эксепшен при создании объекта, но так как такого поведения нет, то придерживаемся мудрого принципа "Явное лучше, чем неявное" и повнимательней пишем свой код.

Всем здоровья)

Комментариев нет:

Отправка комментария