问题
Assume
I am using Django 2.x and use default settings. i.e,
TIME_ZONE = 'UTC'
andUSE_TZ = True
I am recording data in Honolulu, Hawaii, which means 2019-4-9 9pm (user time) in Honolulu is 2019-4-10 in UTC (server time)
Now I want to filter by 2019-4-9 Honolulu time (user time)
Here is what a demo code
class TimelineTable(models.Model):
accessed = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.accessed}'
Here is the data in TimelineTable (recorded in 2019-4-9 Honolulu time)
ID accessed
1 2019-04-10 07:19:30.319881
2 2019-04-10 07:19:35.004506
3 2019-04-10 07:19:37.612088
Without considering timezone, fetch data works fine
>>> TimelineTable.objects.filter(accessed__date=datetime.date(2019, 4, 9))
<QuerySet []>
>>> TimelineTable.objects.filter(accessed__date=datetime.date(2019, 4, 10))
<QuerySet [<TimelineTable: 2019-04-10 07:19:30.319881+00:00>, <TimelineTable: 2019-04-10 07:19:35.004506+00:00>, <TimelineTable: 2019-04-10 07:19:37.612088+00:00>]>
Now the problem is with timezone.
I am talking to server: Hey, give me those entries I recorded in 2019-4-9 at Honolulu.
>>> Honolulu = pytz.timezone("Pacific/Honolulu")
>>> t = datetime.datetime(2019, 4, 9, tzinfo=Honolulu)
>>> TimelineTable.objects.filter(accessed__date=t)
<QuerySet []>
I expected 3 entries, but nothing happens.
How to get these entries, without any bugs?
回答1:
I think this should work:
t = datetime.datetime(2019, 4, 9, 14, 00, 00, tzinfo=Honolulu)
d = t.astimezone(pytz.UTC)
TimelineTable.objects.filter(accessed__date=d.date())
# OR
TimelineTable.objects.filter(accessed__gte=t)
Following code will not work:
t = datetime.datetime(2019, 4, 9, tzinfo=Honolulu)
d = t.astimezone(pytz.UTC)
TimelineTable.objects.filter(accessed__date=d.date())
Explanation
When you generate datetime.datetime(2019, 4, 9)
, it will return time datetime.time(0, 0)
. When you convert it to UTC
, the date won't be changed because its not the time difference between UTC and Honolulu is not 24 hours.
来源:https://stackoverflow.com/questions/55607796/django-filter-date-with-timezone-aware