#34699: Filtering on annotated TruncSecond expression gives unexpected result.
-------------------------------------+-------------------------------------
     Reporter:  Stefan               |                    Owner:  nobody
         Type:  Uncategorized        |                   Status:  new
    Component:  Database layer       |                  Version:  4.2
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Abdulla):

 I believe this would be the case for all other Trunc Date expressions as
 they are subclassed with `TruncBase`.
 Replying to [ticket:34699 Stefan]:
 > With a non-UTC time zone:
 >
 > {{{#!python
 >   TIME_ZONE = 'Europe/Berlin'
 >   }}}
 >
 > and a simply query like so
 >
 > {{{#!python
 >   from django.db.models.functions import TruncSecond
 >   from django.utils import timezone
 >
 >   book = Book.objects.get(id=2)
 >   now = timezone.now()
 >   book.published = now
 >   book.save()
 >
 Book.objects.annotate(_published_trunc=TruncSecond('published')).filter(id=2,
 _published_trunc__lte=now)
 >   }}}
 >
 > The result is empty; I have simply filtered `now` against a second-
 trunced version of `now` so I would expect a result.
 >
 > However under the hood the `_published_now` column is converted to a
 naive timestamp using `AT TIME ZONE 'Europe/Berlin'` and is thus a naive
 timestamp 2 hours ''ahead'' of UTC.
 >
 > {{{#!sql
 > SELECT "book"."id",
 >        "book"."published",
 >        DATE_TRUNC('second', "book"."published" AT TIME ZONE
 'Europe/Berlin') AS "_published_trunc"
 > FROM "book"
 > WHERE ("book"."id" = 2 AND
 >        DATE_TRUNC('second', "book"."_published_trunc" AT TIME ZONE
 'Europe/Berlin') <=
 >        '2023-07-04 11:59:00+02:00'::timestamptz)
 > }}}
 >
 >
 > The filter compares a naive timestamp to an aware one, but assumes the
 LHS naive timestamp is a UTC timestamp - which it is not, it is Berlin
 time.
 >
 > **Workaround**
 >
 > 1) Use `TruncSecond(now)` in the filter so the compared naive timestamps
 are the same.
 >
 > 2) Use `_published_trunc=TruncSecond('published',
 tzinfo=datetime.timezone.utc)` - I don't like this though. It's not clear
 without a comment why the tzinfo is needed ''and'' it assumes the database
 will compare timezones using UTC.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34699#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701893228280c-d6873e19-29ef-4fc8-b388-311648278491-000000%40eu-central-1.amazonses.com.

Reply via email to