Hi,
while debugging test failures in our CI, which do not happen locally, I came across the following behavior: With django 4.0 (or 3.2, or 3.1), psycopg2 >=2.8.4 (up to current), postgres 13 (no other versions tested), a DateTimeField
does not retrieve the same value it was given initially:
posted = timezone.now()
p1 = Post.objects.create(posted=posted)
p2 = Post.objects.get(pk=p1.pk)
print(p1.posted)
print(p2.posted)
print("equal", p1.posted == p2.posted)
yields
2022-02-01 12:23:52.952457+00:00
2022-02-01 13:23:52.952457+00:00
equal False
I expected the two values to be exactly same, or to be the same after you take time zones into account. Instead, they differ by one hour.
Relevant settings:
TIME_ZONE = 'Europe/Berlin'
USE_I18N = True
USE_TZ = True
After more investigation I noticed that this only happens when the app server time zone (Europe/Berlin
) differs from the postgresql timezones (in this case, Etc/UTC
). Changing either the timezone in postgres or forcing the connection onto the same one resolves the issue.
While this is a feasible workaround, the behavior still is very odd to me.
Feel free to try it yourself in this small demo:
$ git clone https://github.com/luto/django_tztest
$ cd django_tztest
$ ./demo.sh
(...)
2022-02-01 12:23:52.952457+00:00
2022-02-01 13:23:52.952457+00:00
equal False
Note that you will need docker/docker-compose, which contains the postgres instance. You can also use bring your own (make sure its time zone is Etc/UTC!) by adapting the django config accordingly.
I already had another dev try this on their machine, which shows the same behavior. I expect it to show similar behavior on any dev machine (or app server) that’s not UTC.
Any hints? Thank you for taking a look!