#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 [email protected].
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