проблемы с time () и date () после изменения времени (DST — standard)

#php #date #time #dst

#php #Дата #время #летнее время

Вопрос:

В PHP я хотел бы вывести список опций HTML, содержащий даты на следующие 14 дней.

Эти встречи всегда назначены на 18 часов:

 $today_day = date('d');
$today_month = date('m');
$today_year = date('Y');
$date_entry = mktime(18, 00, 00, $today_month, $today_day, $today_year);
$optionsStr = '<select name="date">';
for ($d = 1; $d < 14; $d  ) {
    $date_entry_temp = $date_entry 86400*$d;
    $optionsStr .= '<option value="'.$date_entry_temp.'">'.date('d.m.Y', $date_entry_temp).'</option>';
}
$optionsStr .= '</select>';
echo $optionsStr;
  

Затем пользователь может выбрать одну из этих дат и отправить форму. Затем выбранная временная метка вставляется в базу данных.

Итак, у меня есть несколько записей в моей базе данных.

На другой странице есть список текущих встреч:

 mysql_query("SELECT id, name FROM appointments WHERE date_time = ".time());
  

Итак, в 18 часов должен быть какой-то вывод, поскольку в базе данных есть записи за этот день. Это работает отлично, пока время не изменится с DST на стандартное время или наоборот. Тогда, действительно, неправильно:

Назначенные встречи отображаются на час позже или слишком рано соответственно.

Как я могу решить эту проблему?

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

1. Пожалуйста, прекратите писать теги в заголовках. Вы сделали это по многим из ваших 112 вопросов.

2. Извините, я не знал, как этого избежать. Извините, я должен более внимательно прочитать рекомендации.

3. 18 часов, я уверен, вы имеете в виду 1800 часов. (Тысяча восемьсот часов)

4. Нет, я имел в виду то, что сказал: 18 часов, то есть 6 вечера.

Ответ №1:

mktime() создает временную метку unix. Временная метка unix — это количество секунд с 1 января 1970 года, 00:00:00 GMT 0000. (по Гринвичу)

Когда вы устанавливаете свой часовой пояс в «Европа / Берлин», часовой пояс либо GMT 0100 (зимой), либо GMT 0200 (летом). Это означает, что время ваших встреч по Гринвичу изменяется на один час при использовании DST. Это означает, что время между первой встречей до изменения и следующей встречей после изменения составляет не 24 часа, а 23 или 25. Однако вы генерируете встречи, добавляя 86400 секунд = 24 часа.

Вместо этого вы можете использовать объект DateTime и метод add(). Он учитывает изменения летнего времени.

 // create a new date object with todays date
$date = new DateTime();
// set the time to 18:00
$date->setTime(18,0,0);
$optionsStr = '<select name="date">';
for ($i = 0; $i < 14; $i  ) {
    // add 1 day
    $date->add(new DateInterval('P1D'));
    $optionsStr .= '<option value="'.$date->format('U').'">'.$date->format('d.m.Y').'</option>';
}
$optionsStr .= '</select>';
echo $optionsStr;
  

Смотрите http://www.php.net/manual/en/datetime.add.php для получения дополнительной информации.

Ответ №2:

Ваша основная проблема заключается в том, что вы не работаете с датами GMT. Вот красочный пост, в котором освещаются возникающие подводные камни:

http://derickrethans.nl/storing-date-time-in-database.html

Что вам следует делать, так это сохранять даты ваших встреч в часовом поясе UTC, сравнивать даты и время в часовом поясе UTC и отображать даты и время пользователям в вашем (ок) или их (идеальном) предпочтительном часовом поясе.

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

1. На самом деле, оригинальный плакат уже хранит временные метки в UTC, а статья, на которую вы ссылаетесь, предлагает обратное: сохранять время по местному времени вместе с часовым поясом. (Где под «локальным» я подразумеваю «в месте события». Обычно события происходят в определенное время в определенном месте, а не по определенному времени по Гринвичу)

Ответ №3:

Кажется, у вас проблема с часовыми поясами: http://dev.mysql.com/doc/refman/5.0/en/timestamp.html Я бы выбрал время, преобразовал из вашего местного времени в UTC, а затем поместил его в базу данных. Если вы прочитали это, преобразуйте обратно из UTC в ваше местное время.

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

1. Поскольку я использую столбцы INT (10) для своих временных меток, проблем с часовыми поясами быть не должно, верно? MySQL не может знать, что это временная метка, поэтому ошибка должна быть в PHP.

2. Кстати, это не упрощает вычисления.

Ответ №4:

При использовании времени, пожалуйста, убедитесь, что вы всегда УСТАНАВЛИВАЕТЕ ЧАСОВОЙ пояс либо в вашем php.ini, либо в вашем коде. И вы мало что можете сделать с вашими записями в базе данных, если вы отсортируете их по времени или дате, они в конечном итоге будут чередоваться из-за того, что новая дата предшествует дате вашей последней записи до изменения времени.

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

1. Я ВСЕГДА устанавливаю часовой пояс в своем коде, используя date_default_timezone_set (‘Европа / Берлин’). И не должно быть скачка или перекрытия, поскольку время в метке времени всегда непрерывное.