Поля даты и времени MySQL и летнее время — как я ссылаюсь на “дополнительный” час?

Просто должен использовать условную проверку существование параметра. Например:

where (string.IsNullOrEmpty(ProductNumber) || ProductNumber == tags.productNumber)

Тот путь, если номер продуктов не вводится, что выражение возвратит true во всех случаях, но если это вводится, это только возвратит true при соответствии.

83
задан Lance Roberts 21 January 2010 в 22:01
поделиться

4 ответа

Типы дат MySQL, откровенно говоря, не работают и не могут правильно хранить все значения времени, если в вашей системе не установлен часовой пояс с постоянным смещением, такой как UTC или GMT-5. (Я использую MySQL 5.0.45)

Это потому, что вы не можете сохранять любое время в течение часа до окончания летнего времени . Независимо от того, как вы вводите даты, каждая функция даты будет обрабатывать это время, как если бы они были в течение часа после переключения.

Часовой пояс моей системы - America / New_York . Давайте попробуем сохранить 1257051600 (вс, 01 ноября 2009 г., 06:00:00 +0100).

Здесь используется собственный синтаксис INTERVAL:

SELECT UNIX_TIMESTAMP('2009-11-01 00:00:00' + INTERVAL 3599 SECOND); # 1257051599
SELECT UNIX_TIMESTAMP('2009-11-01 00:00:00' + INTERVAL 3600 SECOND); # 1257055200

SELECT UNIX_TIMESTAMP('2009-11-01 01:00:00' - INTERVAL 1 SECOND); # 1257051599
SELECT UNIX_TIMESTAMP('2009-11-01 01:00:00' - INTERVAL 0 SECOND); # 1257055200

Даже FROM_UNIXTIME () не вернет точное время.

SELECT UNIX_TIMESTAMP(FROM_UNIXTIME(1257051599)); # 1257051599
SELECT UNIX_TIMESTAMP(FROM_UNIXTIME(1257051600)); # 1257055200

Как ни странно, DATETIME будет по-прежнему сохранять и возвращать (только в строковой форме!) Раз в пределах "

43
ответ дан 24 November 2019 в 08:54
поделиться

Но как мне сохранить что-нибудь до 01:30:00 -04: 00?

Вы можете преобразовать в UTC следующим образом:

SELECT CONVERT_TZ('2009-11-29 01:30:00','-04:00','+00:00');


Еще лучше, сохраните даты как поле TIMESTAMP . Это всегда сохраняется в формате UTC, а UTC не знает о летнем / зимнем времени.

Вы можете конвертировать из UTC в местное время, используя CONVERT_TZ :

SELECT CONVERT_TZ(UTC_TIMESTAMP(),'+00:00','SYSTEM');

Где «+00: 00» - это UTC, часовой пояс из, а «SYSTEM» - это местный часовой пояс ОС, в которой работает MySQL. .

3
ответ дан 24 November 2019 в 08:54
поделиться

Я понял это для моих целей. Я резюмирую то, что я узнал (извините, эти заметки многословны; они предназначены для моего будущего обращения, как и все остальное).

В отличие от того, что я сказал в одном из моих предыдущих комментариев, поля DATETIME и TIMESTAMP do ведут себя иначе. Поля TIMESTAMP (как указано в документации) принимают все, что вы отправляете, в формате «ГГГГ-ММ-ДД чч: мм: сс» и преобразуют его из текущего часового пояса в время в формате UTC. Обратное происходит прозрачно всякий раз, когда вы извлекаете данные. Поля DATETIME не выполняют это преобразование. Они берут все, что вы им отправляете, и просто сохраняют это напрямую.

Ни типы полей DATETIME, ни TIMESTAMP не могут точно хранить данные в часовом поясе, который соблюдает DST . Если вы храните «2009-11-01 01:30:00» в полях невозможно определить, какая версия 1:30 вам нужна - версия -04: 00 или -05: 00.

Хорошо, поэтому мы должны хранить наши данные в часовом поясе, отличном от DST (например, в UTC) . Поля TIMESTAMP не могут точно обрабатывать эти данные по причинам, которые я объясню: если ваша система настроена на часовой пояс DST, то то, что вы вводите в TIMESTAMP, может быть не тем, что вы получите обратно. Даже если вы отправите ему данные, которые вы уже преобразовали в UTC, он все равно примет данные в вашем местном часовом поясе и выполнит еще одно преобразование в UTC. Этот принудительный TIMESTAMP-обратный переход от локального к UTC-обратно к локальному происходит с потерями, когда в вашем часовом поясе соблюдается летнее время (поскольку «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 не работают должным образом вокруг границ летнего времени, если вы храните свои даты в 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. Например: с классом DateTime PHP вы можете указать «2009-11-01 1:30:00 EST» отдельно от «2009-11-01 1:30:00 EDT», затем преобразуйте его в UTC и сохраните правильное время UTC в поле DATETIME.

Уф. Большое спасибо за вклад и помощь. Надеюсь, это избавит кого-то от головной боли в будущем.

Кстати, я вижу это в MySQL 5.0.22 и 5.0.27

67
ответ дан 24 November 2019 в 08:54
поделиться

Я думаю, что ссылка Микавиттмана предлагает лучшее практическое решение этих ограничений MySQL: Установите часовой пояс сеанса на UTC при подключении:

SET SESSION time_zone = '+0:00'

Затем вы просто отправляете ему временные метки Unix, и все должно быть в порядке.

13
ответ дан 24 November 2019 в 08:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: