I have multiple places in my application where I calculate the number of days it has been since a date field. Because this is used in the middle of filtering and QuerySet operations this must be done w/ Postgres database functions. As of 3.1 the following code worked just fine, but starting in 3.2 it throws an exception. For reference, IncidentReport is a class with a simple date field called (imaginatively) date.
# Code that dies a terrible death
temp_ban_incidents = IncidentReport.objects.all().annotate(
time_diff=ExpressionWrapper(Now() - F("date"), output_field=DurationField())
)
temp_ban_incidents.count() # ok so far
for incident in temp_ban_incidents:
print(incident, incident.time_diff, type(incident.time_diff))
# this confirms that yes, we have a bunch of datetime.timedelta fields correctly calculated
temp_ban_incidents = temp_ban_incidents.annotate(
days_since_ban=ExtractDay("time_diff", tzinfo=timezone.utc),
)
temp_ban_incidents.count() # not ok due to the following exception:
...
File "/Users/bixbyr/anaconda3/envs/Shelterware_v2/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 50, in setup_query
self.select, self.klass_info, self.annotation_col_map = self.get_select()
File "/Users/bixbyr/anaconda3/envs/Shelterware_v2/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 267, in get_select
sql, params = self.compile(col)
File "/Users/bixbyr/anaconda3/envs/Shelterware_v2/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 463, in compile
sql, params = node.as_sql(self, self.connection)
File "/Users/bixbyr/anaconda3/envs/Shelterware_v2/lib/python3.8/site-packages/django/db/models/functions/datetime.py", line 50, in as_sql
raise ValueError('tzinfo can only be used with DateTimeField.')
ValueError: tzinfo can only be used with DateTimeField.
I have tried removing the tzinfo argument but that produces another joyful exception when the annotation is evaluated:
function pg_catalog.timezone(unknown, interval) does not exist
LINE 1: ...D U0."season_id" = 482) GROUP BY U0."client_id")) AT TIME ZO...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
For reference, In settings we have
In settings:
USE_TZ = True
TIME_ZONE = 'US/Pacific'
US_PACIFIC_TIMEZONE = pytz.timezone('US/Pacific') # this is the normal arg to tzinfo
I would really appreciate some help, this has been an absolute nightmare with no clear end in sight. Thanks.