Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django filter __date with timezone aware

Assume

  1. I am using Django 2.x and use default settings. i.e, TIME_ZONE = 'UTC' and USE_TZ = True

  2. 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?

like image 402
anonymous Avatar asked Apr 10 '19 08:04

anonymous


1 Answers

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.

like image 96
ruddra Avatar answered Oct 11 '22 18:10

ruddra