ОБНОВЛЕНИЕ 8 апреля 2019 г.
Это известная ошибка для django ‹= 2.2, исправленная на данный момент PR
=================================
(Мы предполагаем бэкенды mysql)
Я могу установить TIME_ZONE
несколько раз в settings.py
, один для глобального приложения django и один для каждой базы данных (см. https://docs.djangoproject.com/en/1.11/ref/settings/#time-zone (ref1))
Обычно используется устаревшая база данных, где время не хранится в формате UTC.
Нет поиска по дате
Этот параметр учитывается при запросе моей базы данных, например :
In settings.py
USE_TZ = True
TIME_ZONE = 'Europe/Paris' # tz1
DATABASES = {
'legacy': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '....cnf',
},
'TIME_ZONE': 'Europe/Paris', # tz2
},
'default' : {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '....cnf',
},
}
}
В manage.py shell
>>> dt = timezone.make_aware(datetime.datetime(2017, 7, 6, 20, 50))
>>> dt
datetime.datetime(2017, 7, 6, 20, 50, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:00:00 DST>)
>>> MyModel.objects.filter(my_datetime_field=dt).exists()
True
Это работает, потому что моя база данных читает '2017-07-06 20:50:00'
С поиском по дате
Связанный документ https://docs.djangoproject.com/en/1.11/ref/models/querysets/#date (ref2)
Но это не работает, хотя по логике должно
>>> MyModel.objects.filter(my_datetime_field__date=dt.date()).exists()
False*
Связанный SQL-запрос от DEBUG:
SELECT (1) AS `a` FROM `my_model` WHERE DATE(CONVERT_TZ(`my_model`.`my_datetime_field`, 'UTC', 'Europe/Paris')) = '2017-07-06' LIMIT 1;
(*) Обратите внимание, что я не заполнил таблицу часовых поясов в MySQL, поэтому в этом случае результат должен быть True
, но может быть False
около полуночи. Связанный документ: https://dev.mysql.com/doc/refman/5.7/en/mysql-tzinfo-to-sql.html.
Две вещи неверны. Во-первых, преобразование должно быть из Парижа в Париж, а не из UTC в Париж. Преобразование должно происходить из часового пояса базы данных tz2 в приложение django one tz1.
Действительно из ref1:
Когда USE_TZ имеет значение True и база данных не поддерживает часовые пояса (например, SQLite, MySQL, Oracle), Django считывает и записывает дату по местному времени в соответствии с этим параметром, если он установлен, и в формате UTC, если он нет.
и ref2:
Если для параметра USE_TZ установлено значение True, поля перед фильтрацией преобразуются в текущий часовой пояс.
Во-вторых, когда tz1 == tz2, нет необходимости использовать CONVERT_TZ
, и запрос будет работать без таблиц часовых поясов в MySQL.
Явные запросы:
mysql> SELECT (1) AS `a` FROM `my_model` WHERE `my_model`.`my_datetime_field` = '2017-07-06 20:50:00' LIMIT 1;
+---+
| a |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
mysql> SELECT (1) AS `a` FROM `my_model` WHERE DATE(`my_model`.`my_datetime_field`) = '2017-07-06' LIMIT 1;
+---+
| a |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
Почему в запросе отображается 'UTC'
? Разве не должно быть 'Europe/Paris'
?
Я что-то неправильно понял из документа или это ошибка?
Спасибо.
РЕДАКТИРОВАТЬ: Моя система tz - это не UTC, если это поможет
mysql> SELECT @@global.time_zone, @@session.time_zone, @@system_time_zone;
+--------------------+---------------------+--------------------+
| @@global.time_zone | @@session.time_zone | @@system_time_zone |
+--------------------+---------------------+--------------------+
| SYSTEM | SYSTEM | CEST |
+--------------------+---------------------+--------------------+