How it is right now

As I understand it right now, this is how datetime works in Django:

For anything that implements time.tzset(), Django sets the timezone for the entire runtime to settings.TIME_ZONE. This means on Windows the setting is ignored. Django on Windows will operate in whatever timezone is specified on the OS.

EXCEPT in the case of PostgreSQL backend, where the db connection initializes with cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE]). Since timestamp and time fields are created with time zone, this means PostgreSQL will return datetime values typecasted to settings.TIME_ZONE first.

Proposed solution

PostgreSQL should not have time zone set, or have time zone set to 'UTC'.

Django should store all datetime on DB backends as naive UTC datetime.

settings.TIME_ZONE becomes a site-wide runtime typecast directive. This way settings.TIME_ZONE can be optional if someone doesn't care about time zones in their application. In that case it feels more natural to operate in the timezone of the server hosting Django. The default return from model.some_datetime_field could be: