Функция PHP strtotime () неверна на 1 час?

Я конвертирую дату и время в метки времени с помощью PHP, прежде чем они будут вставлены в мою базу данных MySQL.

Моя проблема в том, что когда я использую функцию PHP strtotime, временная метка вывода на -1 час отстает от моего фактического времени.

Например, учитывая сегодняшнюю дату: 21.07.2010. Когда я использую PHP-код, например:

<?php
$my_timestamp = strtotime("07/21/2010");
echo $my_timestamp;
?>

Временная метка, отправленная обратно, соответствует Гринвичу МИНУС 1 час. т.е. я возвращаюсь: 20 июля 2010 г., 23:00:00 по Гринвичу, а не 21 июля 2010 г., 00:00:00 по Гринвичу.

Я живу в Великобритании, поэтому мой часовой пояс - GMT. Я указал свой часовой пояс в скрипте, используя date_default_timezone_set ('Europe / London'), и я также убедился, что для файла php.ini установлено значение 'Europe / London'.

Возможно, это связано с переходом на летнее время? Как я могу решить проблему, не добавляя 1 час ко всем моим датам?


person David    schedule 21.07.2010    source источник
comment
Если вам просто нужно добавить 1 час к датам, добавьте 3600 к метке времени (3600 секунд = 1 час)   -  person NullUserException    schedule 22.07.2010
comment
Ваш часовой пояс отличается от GMT, в Великобритании сейчас летнее время, которое составляет GMT +1.   -  person nos    schedule 22.07.2010
comment
@nos Почему бы не добавить это в качестве ответа, я думаю, что это правильный ответ.   -  person Pekka    schedule 22.07.2010
comment
просто чтобы уточнить, GMT как часовой пояс все еще существует, даже когда нас в Великобритании нет. Наш часовой пояс прямо сейчас - BST (GMT + 1), поэтому ваше ошибочное предположение о том, что вы находитесь в GMT, является причиной вашей проблемы, как уже указывалось. Не хуже того парня из Калифорнии, который сказал мне, что он всегда на PDT круглый год :(   -  person    schedule 22.07.2010


Ответы (3)


Европейское / лондонское время отличается от времени по Гринвичу при переходе на летнее время. Вам нужно установить его в UTC.

date_default_timezone_set('UTC');

date_default_timezone_set('GMT'); может работать, но, как отмечает Кеннет в комментарии ниже, он устарел.

person Yahel    schedule 21.07.2010
comment
ВНИМАНИЕ: GMT с тех пор не используется в более поздних версиях PHP, и, хотя он все еще временно поддерживается, настоятельно рекомендуется использовать вместо него UTC. - person Kenneth; 03.01.2012
comment
@Kenneth Добавил примечание. Спасибо! - person Yahel; 03.01.2012

Часовой пояс Лондона выражается в летнем британском времени. При этом рекомендуется хранить время в UTC и представлять время конечному пользователю либо в UTC, либо в ИХ местном времени.

Также, вероятно, разумно убедиться, что ваше системное время - UTC.

person Elf King    schedule 21.07.2010

До PHP 5.3 у strtotime были проблемы с вычислением времени, если вы добавляли или вычитали месяцы и дни и т.д. обновите свою версию PHP.

person Gleiemeister 2000    schedule 21.07.2010
comment
Уверены, что это не ваше понимание функций даты и времени PHP? - person Daniel Egeberg; 22.07.2010
comment
‹? Php эхо-дата (Y-m-d, strtotime (31.01.2009 +1 месяц)). ‹Br›; ? ›Попробуй. - person Gleiemeister 2000; 22.07.2010
comment
@Android Noob Я не уверен, что хочу, чтобы это сработало. 1 месяц не является фиксированной единицей измерения. Это может быть 28, 29, 30 или 31 день в зависимости от месяца, в отличие от других интерпретаций strtotime (), которые работают (+1 день, +1 неделя), которые всегда являются фиксированным количеством времени, независимо от того, когда они происходят. . (Тем не менее, я не из тех, кто вам противостоит). - person Yahel; 22.07.2010
comment
То же самое может произойти, если вы добавите или вычтете количество дней, что должно работать только в одном направлении. Если вы превысите определенные пороги, будет возвращена неверная дата. Если это не ошибка, скажите мне, что это такое. - person Gleiemeister 2000; 22.07.2010
comment
Так я и ожидал. +1 month просто увеличивает часть месяца на 1. Поскольку 2009-02-31 не существует, оно переполняется до 03. Это соответствует спецификациям GNU. Вы можете использовать first day of next month или last day of next month. - person Daniel Egeberg; 22.07.2010
comment
@yc Это потому, что 2008 год - високосный. Таким образом, 2008-02-31 переполняется до 2008-03-02. - person NullUserException; 22.07.2010
comment
@yc: Просто потому, что 2008 год был високосным, а в феврале было 29 дней. 2009-02-31, это на три дня больше в феврале, поэтому он переходит к 3 марта. 2008-02-31, это на два дня больше, чем в феврале, поэтому он переходит на 2 марта. Вы можете попробовать себя с 2010-02-28 +1 month, это станет 2010-03-28, как и ожидалось, потому что это просто увеличивает часть месяца. - person Daniel Egeberg; 22.07.2010
comment
@ Даниэль Эгеберг, тогда почему 2010-06-31 + 1 month получает меня 1 августа, а 2010-06-28 + 1 month получает меня 28 июля? Это довольно странно. - person Yahel; 22.07.2010
comment
@yc Это совсем не круто. В июне нет 31 дня. - person NullUserException; 22.07.2010
comment
@NullUserException ... Мне пора домой. В моем часовом поясе я должен был уйти с работы час назад. Ясно, что мой мозг перегорел. Вы правы, ребята; Я не прав. Ой. - person Yahel; 22.07.2010
comment
@yc Поскольку 2010-06-31 не существует, он переполняется на 2010-07-01. Затем вы добавляете один месяц и получаете 2010-08-01. - person Daniel Egeberg; 22.07.2010
comment
Что ж, мы можем не согласиться с тем, что требуется для ошибки, но: Воспроизвести код: --------------- ‹? $ t = strtotime (1 января 2008 г.); эхо-дата (c \ n, strtotime (+1 месяц, $ t)); $ t = strtotime (29 января 2008 г.); эхо-дата (c \ n, strtotime (+1 месяц, $ t)); $ t = strtotime (31 января 2008 г.); эхо-дата (c \ n, strtotime (+1 месяц, $ t)); $ t = strtotime (29 февраля 2008 г.); эхо-дата (c \ n, strtotime (+1 месяц, $ t)); ? ›Производит: 2008-02-01T00: 00: 00-08: 00 2008-02-29T00: 00: 00-08: 00 2008-03-02T00: 00: 00-08: 00 2008-03-29T00: 00 : 00-07: 00 Вот почему они в php 5.3 изменили его, чтобы вы могли правильно рассчитать - person Gleiemeister 2000; 22.07.2010
comment
@Android Noob: Не знаю, о чем ты говоришь. Этот сценарий имеет точно такой же (правильный!) Вывод как в PHP 5.2, так и в PHP 5.3. Не стесняйтесь отправлять его как ошибку на bugs.php.net, но я гарантирую, что он будет закрыт как подделка. - person Daniel Egeberg; 22.07.2010
comment
@Android: именно то, что вы ожидаете от него. Обоснование созданных дат было подробно объяснено Дэниелом Эгебергом. В чем проблема? - person NullUserException; 22.07.2010
comment
вы оба можете начать читать журнал изменений прямо здесь: php.net/manual/en/function .strtotime.php исправлены несколько ошибок. Затем, во-вторых, был реализован «последний день следующего месяца», потому что функция была несовместимой. Последовательность важна при вычислении дат afaik. - person Gleiemeister 2000; 22.07.2010
comment
@Android Как это не согласованно? +1 месяц добавляет 1 месяц к месячной части даты. Если эта дата не существует, она выходит за пределы. Это происходит последовательно с момента создания функции. То, что он не соответствует вашему концептуальному представлению о том, что он должен делать, не означает, что он ошибочен. Функция ведет себя стабильно и правильно. Фактически, Jan-31 + 1 month = Mar 2nd имеет смысл. Что вы ожидали от него? - person NullUserException; 22.07.2010
comment
Последовательный: con · sist · ent / kənˈsistənt / Прилагательное 1. (человека, поведения или процесса) Неизменный в достижении или эффекте в течение определенного периода времени. - person NullUserException; 22.07.2010
comment
Я понимаю вашу точку зрения, но все же думаю, что она должна переполниться, потому что это уже не фиксированная сумма, если вы добавите месяц. Также я обнаружил ошибку, от которой мы столкнулись в журнале изменений в PHP 5 до 5.2.7, когда запрос определенного наступления данного дня недели в месяце, когда этот будний день был первым днем ​​месяца, неправильно добавлял одну неделю к возвращаемой метке времени. . Это было исправлено в 5.2.7 и более поздних версиях. - person Gleiemeister 2000; 22.07.2010