ORM-запрос вытягивает объекты за пределы диапазона дат из-за изменения часового пояса
У меня есть часть унаследованного кода, который использует интерполированный SQL с psycopg2 для выполнения запроса. Однако я хотел убрать это и сделать так, чтобы код использовал только ORM. Однако у меня возникла проблема, когда мой ORM-запрос выводит результаты за пределы заданного диапазона дат, когда часовой пояс установлен не на UTC.
Например, учитывая следующую модель:
class Dinner(models.Model):
eaten_at = models.DateTimeField()
И давая следующие произвольные объекты, которые есть в моей базе данных:
Dinner(id=1, eaten_at=2022-02-23 16:58:11+00:00)
Dinner(id=2, eaten_at=2022-02-23 23:59:59+00:00)
Dinner(id=3, eaten_at=2022-02-24 00:00:00+00:00)
Dinner(id=4, eaten_at=2022-02-24 00:00:00+00:00)
Я хотел выполнить запрос для Ужинов, съеденных 2022-02-24 или после 2022-02-24
eaten_after_date = datetime.datetime.combine(datetime.datetime.strptime("2022-02-24", "%Y-%m-%d"),datetime.time(0, 0, 0))
# datetime.datetime(2022, 2, 24, 0, 0)
Мой код Psycopg2 выглядел следующим образом:
cursor.execute("SELECT * FROM dinner WHERE dinner.eaten_at >= %s with time zone", eaten_after_date)
Как и ожидалось, в результате получаются две строки с соответствующими ID 3 и 4.
Я переписал это, используя только ORM, следующим образом:
Dinner.objects.filter(eaten_at__gte=eaten_after_date)
И в некоторых случаях это работает. Однако, когда у меня в настройках есть следующее:
TIME_ZONE = "Asia/Tokyo"
Я возвращаю объекты до 24-го (в данном конкретном примере - возвращаются ВСЕ строки). Например, получение первого отсортированного результата возвращает запись, начиная с 23-го:
record.objects.filter(meta_end_date__gte=eaten_after_date).order_by('eaten_at').first().eaten_after_date
>>> 2022-02-23 16:58:11+00:00
Это странно - мое указанное время даты datetime.datetime(2022, 2, 24, 0, 0), а я получаю результаты от 23-го числа! Я уверен, что это какая-то проблема с часовым поясом при интерполяции запроса. Однако... я не знаю, как это исправить.
Я пробовал:
eaten_after_date = timezone.make_aware(eaten_after_date)
# and
eaten_after_date = eaten_after_date.astimezone()
Однако я совершенно не могу воспроизвести результаты запроса из моего предыдущего запроса Psycopg2 в чистый запрос ORM.
Мне кажется, что я упускаю что-то очень простое, и я совершенно не знаю что.