Я понял это для моих целей. Я суммирую то, что я узнал (извините, эти заметки многословны; они так же важны для моего будущего обращения, как и все остальное).
Вопреки тому, что я сказал в одном из моих предыдущих комментариев, поля DATETIME и TIMESTAMP do ведут себя по-разному. Поля TIMESTAMP (как указывают документы) берут все, что вы отправляете, в формате «ГГГГ-ММ-ДД чч: мм: сс» и преобразует его из текущего часового пояса в время UTC. Обратное происходит прозрачно всякий раз, когда вы получаете данные. Поля DATETIME не делают это преобразование. Они берут все, что вы им отправляете, и просто храните это напрямую.
Ни типы полей DATETIME, ни TIMESTAMP не могут точно хранить данные в часовом поясе, который соблюдает DST . Если вы храните «01-11-2009, 01:30:00», в полях нет никакой возможности определить, какую версию 1:30 вы хотели - версию -04: 00 или -05: 00.
Хорошо, поэтому мы должны хранить наши данные в часовом поясе не в летнее время (например, в формате UTC). Поля TIMESTAMP не могут обрабатывать эти данные точно по причинам, которые я объясню: если ваша система настроена на часовой пояс DST, то то, что вы поместили в TIMESTAMP, может быть не тем, что вы получите обратно. Даже если вы отправите ему данные, которые вы уже преобразовали в UTC, он все равно будет предполагать, что данные находятся в вашем местном часовом поясе, и выполнит еще одно преобразование в UTC. Эта вынужденная обратная поездка по местному-UTC-обратно-локальному времени с применением TIMESTAMP вызывает потери, когда ваш местный часовой пояс соблюдает летнее время (поскольку «2009-11-01 01:30:00» отображается в 2 различных возможных времени).
С DATETIME вы можете хранить свои данные в любом часовом поясе и быть уверенным, что получите все, что отправите (вы не будете вынуждены переходить с потерями туда и обратно, на что навязывают вам поля TIMESTAMP). Таким образом, решение состоит в том, чтобы использовать поле DATETIME и перед сохранением в поле преобразовать из системного часового пояса в любую зону без DST, в которой вы хотите его сохранить (я думаю, что UTC, вероятно, лучший вариант). Это позволяет вам встроить логику преобразования в ваш язык сценариев, чтобы вы могли явно сохранить UTC-эквивалент "2009-11-01 01:30:00 -04: 00" или "" 2009-11-01 01:30: 00 -05: 00 ".
Еще одна важная вещь, которую стоит отметить, - это то, что математические функции даты / времени в MySQL не работают должным образом вокруг границ DST, если вы храните даты в DST TZ. Так что все больше причин экономить на UTC.
Короче говоря, теперь я делаю это:
При извлечении данных из базы данных:
Явно интерпретирует данные из базы данных как UTC за пределами MySQL, чтобы получить точную метку времени Unix. Для этого я использую функцию PHP strtotime () или ее класс DateTime. Это не может быть надежно сделано внутри MySQL с помощью функций MySQL CONVERT_TZ () или UNIX_TIMESTAMP (), поскольку CONVERT_TZ будет выводить только значение «YYYY-MM-DD hh: mm: ss», которое страдает от проблем неоднозначности, а UNIX_TIMESTAMP () предполагает его вход находится в системном часовом поясе, а не в часовом поясе, в котором данные были фактически сохранены (UTC).
При сохранении данных в базе данных:
Преобразуйте вашу дату в точное время UTC, которое вы хотите за пределами MySQL. Например: с помощью класса PHP DateTime вы можете указать «2009-11-01 1:30:00 EST» отдельно от «2009-11-01 1:30:00 EDT», затем преобразовать его в UTC и сохранить правильное время UTC в поле DATETIME.
Уф. Большое спасибо за каждый вклад и помощь. Надеюсь, это спасет кого-то еще от головной боли в будущем.
Кстати, я вижу это на MySQL 5.0.22 и 5.0.27