问题
I am using flask sqlalchemy and postgreSQL and I have issues with the displayed datetimes, while investigating this issue I found an other weird thing:
Creating a DB entry in incognito mode (chrome browser tab) gives a different/wrong time. EDIT: It has nothing to do with incognito mode, both cases happen in normal mode aswell. I have not figured out yet why.
This is the code:
I changed the default time zone of my database:
ALTER DATABASE postgres SET timezone TO 'Europe/Berlin';
the model:
class User(UserMixin, Base):
__tablename__ = 'users'
date_added = Column(DateTime(timezone=True), nullable=False)
The method I use to add datetime to DB:
date_added=datetime.today()
How it looks in the DB (my localtime at this time was 13:53:46):
Creating entry not in incognito
timestamp with time zone
2019-02-01 13:53:46.73817+01
Creating entry in incognito
timestamp with time zone
2019-02-01 12:53:46.73817+01
This really makes me worry. It is simply wrong. Even if I would convert the datetime objects to localtime. Both entries have been done at the same time, but show different results, how is this possible?
Also when viewing these dates in HTML, postgreSQL does not apply the offset, so the first date looks correct, but the second is wrong.
Initially I just wanted to find a way to store ALL datetime objects in Europe/Berlin and return them in Europe/Berlin time, so I dont have to convert UTC to Europe/Berlin, but now I think something went horribly wrong.
I also have double checked my code everywhere, I am not using other methods to manipulate datetime objects.
EDIT
I am saving a datetime everytime a user logs in. Currently I tried this on not incognito. My localtime is 14:13:33 BUT it saved into the DB:
2019-02-01 13:13:33.804339+01. How is this even possible? I know it cant be random, but right now it looks like its saving times randomly sometimes UTC with offset and sometimes Europe/Berlin with offset.
EDIT
I double checked all tables in question with SHOW timezone; and they all correctly return Europe/Berlin
回答1:
datetime.today() returns a timestamp without timezone info of the current local time (the returned value is timezone naive). The root of your problem is that somewhere between SQL Alchemy's postgres adapter and postgres itself it has to guess at a timezone. As you might imagine, computer systems tend toward assuming UTC if no timezone is explicitly provided, but the precise logic for a toolsuite set can be complex and hard to debug (and my depend on your local time zone settings on your computer, system-level settings in the db, session level settings, and the preference of the toolmaker). You can sidestep this entire can of worms by either:
Storing all of your timestamps without a time zone in UTC, then converting to the desired timestamp as appropriate
Always using timestamps with time zone (i.e. replace
datetime.today()withdatetime.now()and pass in the desired time zone so that you are always dealing with a timezone aware value ), so there is no need for the computer to assume a timezone.
Note that in postgres, the timestamp with time zone type is still always stored as UTC with no extra information, the database simply uses the session-level configuration to decide which time zone to display it as when outputting it.
来源:https://stackoverflow.com/questions/54480171/postgresql-sqlalchemy-and-timestamp-with-time-zone-why-is-incognito-different-f