DateValidator использует timezone UTC при использовании timestampAttribute только с датой, без времени

Предварительное обсуждение найденных ошибок перед отправкой их авторам фреймворка, а также внесение новых предложений.
Ответить
Аватара пользователя
S c
Сообщения: 883
Зарегистрирован: 2012.04.11, 14:46

DateValidator использует timezone UTC при использовании timestampAttribute только с датой, без времени

Сообщение S c »

timezone в php/yii и mysql: Europe/Kiev

В php:

Код: Выделить всё

$dt = new \DateTime('2020-10-13');
$dt->getTimestamp(); // 1602536400
Yii::$app->formatter->asTimestamp($dt); // 1602536400
date("Y-m-d H:i:s", 1602536400); // 2020-10-13 00:00:00
В MySql:
UNIX_TIMESTAMP('2020-10-13') // 1602536400
FROM_UNIXTIME(1602536400) // 2020-10-13 00:00:00
Есть правило:

Код: Выделить всё

public function rules()
{
    [['date'], 'date', 'format' => 'php:d.m.Y', 'timestampAttribute' => 'date'],
}
С виджета (с фронта) приходит дата "13.10.2020"

Код: Выделить всё

// action
public function actionUpdate()
{
    ...
    $model->load(Yii::$app->request->post());
    var_dump($model->date); // "13.10.2020"
    $model->validate(['date']);
    var_dump($model->date); // 1602547200, что равно 2020-10-13 03:00:00 (+3 часа), должно быть 1602536400
}

Код: Выделить всё

\yii\validators\DateValidator
private function parseDateValuePHP($value, $format)
{
    ...
    $hasTimeInfo = (strpbrk($format, 'HhGgisU') !== false);
    $date = DateTime::createFromFormat($format, $value, new \DateTimeZone($hasTimeInfo ? $this->timeZone : 'UTC'));
    ...
}
Как видно, в случае, если $hasTimeInfo === false, временная зона приложения игнорируется, и дата форматируется в UTC.

Я В БД храню дату в unixtime, с фронта мне приходит только дата (для приложения это эквивалентно дата и 00:00:00 времени. Далее, когда я делаю выборки в отчетах я получаю не корректные результаты, т.к. в БД лежит не корректный timestamp, вместо 1602536400, там хранится 1602547200.
Выборка:
$q->andWhere(['>=', 'date', $dateTime->getTimestamp()]);

Если в контроллере я буду использовать значение с временем и исправлю формат даты в правилах валидации:

Код: Выделить всё

// rules:
[['date'], 'date', 'format' => 'php:d.m.Y H:i:s', 'timestampAttribute' => 'date']

Код: Выделить всё

// action:
$model->date .= " 00:00:00";
$model->validate(); // $model->date будет 1602536400
Все работает как мне необходимо. Почему валидатор игнорирует временную зону, если не использовать время? Ведь unixtime в любом случае - это дата со временем.
Ответить