6

So I am trying to filter django models by date. Using either only the year, year+month, or year+month+day_of_month. The strategy I am using now is this:

n.filter(create_date__year=q)
n.filter(create_date__year=q[:4],create_date__month=q[4:6])
n.filter(create_date__year=q[:4],create_date__month=q[4:6],create_date__day=q[6:8])

Where 'q' is a date string in the format of either either 'yyyy', 'yyyymm' or 'yyyymmdd' respectively.

This is working pretty well but django is not taking into account timezone. Django searches based on the UTC times and not the EDT, which is what the actual datetime object is set to.

Is there a way to search the year/month/day of month based on a specific timezone?

Linuxios
  • 34,849
  • 13
  • 91
  • 116
user439299
  • 831
  • 4
  • 12
  • 23

2 Answers2

7

Yes, when support for time zones is enabled, Django stores date and time information in UTC in the database, uses time-zone-aware datetime objects internally, and translates them to the end user’s time zone in templates and forms.

Set USE_TZ = True in your settings file.

Create a time-zone-aware datetime first convert it to utc and use that in your filter.

>>> import datetime
>>> import pytz
>>> 
>>> unaware = datetime.datetime.strptime("20131103", "%Y%m%d")
>>> amsterdam = pytz.timezone('Europe/Amsterdam')
>>> aware = unaware.replace(tzinfo=amsterdam)
>>> d = aware.astimezone(pytz.UTC)
>>> 
>>> unaware
datetime.datetime(2013, 11, 3, 0, 0)
>>> amsterdam
<DstTzInfo 'Europe/Amsterdam' AMT+0:20:00 STD>
>>> aware
datetime.datetime(2013, 11, 3, 0, 0, tzinfo=<DstTzInfo 'Europe/Amsterdam' AMT+0:20:00 STD>)
>>> d
datetime.datetime(2013, 11, 2, 23, 40, tzinfo=<UTC>)
>>> 

Now you can filter your objects with d.

objs = SomeModel.objects.all() 

objs.filter(date__year=d.year)
objs.filter(date__year=d.year, date_month=d.month)
objs.filter(date=d.date)
allcaps
  • 10,945
  • 1
  • 33
  • 54
  • 1
    The time shift of 20 minutes should make you suspicious. Check out this thread for a correct answer: https://stackoverflow.com/questions/24856643/unexpected-results-converting-timezones-in-python – Greg Holst Sep 27 '19 at 13:43
  • Will this work for datetimes like this? `d.replace(hour=8); objs.filter(datetime__hour__gte=d.hour)` – konstunn Jun 03 '20 at 12:35
1

To get the current day in a given timezone, I use the following utils function which might be useful in your case called with the pytz.timezone("America/New_York") argument.

from django.utils.timezone import now

def timezone_today(tz=utc):
    """
    Return the current date in the given timezone :param:`tz`.
    """
    return now().astimezone(tz).date()
sebastibe
  • 586
  • 3
  • 13