PostgreSQL带有时区的SQLalchemy和时间戳,为什么隐身模式不同于正常? [英] PostgreSQL SQLalchemy and timestamp with time zone, why is incognito different from normal?

查看:106
本文介绍了PostgreSQL带有时区的SQLalchemy和时间戳,为什么隐身模式不同于正常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用flask sqlalchemy和postgreSQL,但显示的日期时间有问题,在调查此问题时,我发现了另一个奇怪的事情:



在其中创建数据库条目隐身模式(Chrome浏览器标签)提供了不同/错误的时间。
编辑:与隐身模式无关,两种情况也都在正常模式下发生。我还没有弄清楚为什么。



这是代码:



我更改了默认时区我的数据库:

  ALTER DATABASE postgres将时区设置为欧洲/柏林; 

模型:

  class User(UserMixin,Base):
__tablename__ ='用户'
date_added = Column(DateTime(timezone = True),nullable = False)

我用来向数据库添加日期时间的方法:

  date_added = datetime.today()

在数据库中的外观(我的本地时间)此时是13:53:46):



创建不隐身的条目

 带有时区的时间戳
2019-02-01 13:53:46.73817 + 01

在隐身模式下创建条目

 带时区的时间戳
2019-02-01 12:53:46.73817 +01

这真的让我担心。这是完全错误的。即使我将datetime对象转换为localtime。这两个条目都是同时完成的,但显示的结果不同,这怎么可能?



此外,当以HTML格式查看这些日期时,postgreSQL不会应用偏移量,因此,第一个日期看起来正确,但是第二个错误。



最初,我只是想找到一种在欧洲/柏林存储所有日期时间对象并将其返回欧洲的方法。 /柏林时间,所以我不必将UTC转换为欧洲/柏林,但是现在我认为出了点大问题。



我也到处都仔细检查过我的代码,我我没有使用其他方法来操纵日期时间对象。



编辑



我是每次用户登录时保存日期时间。目前,我以隐身模式尝试过此操作。我的本地时间是 14:13:33 但保存到数据库中:
2019-02-01 13:13:33.804339 + 01 。这怎么可能?我知道它不能是随机的,但是现在看来,它的保存时间是随机的,有时UTC带有偏移,有时是欧洲/柏林带有偏移。



编辑



我用 SHOW时区仔细检查了所有有问题的表; ,它们都正确返回了欧洲/柏林

解决方案

datetime.today()返回没有时区信息的时间戳当前本地时间(返回值是时区 naive )。问题的根源在于,在SQL Alchemy的postgres适配器和postgres本身之间的某个地方,它必须猜测一个时区。您可能会想像,如果未明确提供时区,则计算机系统倾向于采用UTC,但是用于工具套件的精确逻辑可能很复杂且难以调试(而且取决于系统级计算机的本地时区设置)数据库中的设置,会话级别设置以及工具制造商的偏好设置)。您可以通过以下两种方法来避开整个蠕虫病毒:


  1. 在UTC中存储没有时区的所有时间戳,然后进行转换


  2. 始终使用带时区的时间戳(即替换 datetime.today() datetime.now()并传递所需的时区,以便您始终处理时区 aware value),因此


请注意,在postgres中,时间戳带有时区类型的数据始终始终存储为UTC,没有任何额外的信息,数据库仅使用会话级配置来决定在输出时区时将其显示为哪个时区。


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

解决方案

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:

  1. Storing all of your timestamps without a time zone in UTC, then converting to the desired timestamp as appropriate

  2. Always using timestamps with time zone (i.e. replace datetime.today() with datetime.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.

这篇关于PostgreSQL带有时区的SQLalchemy和时间戳,为什么隐身模式不同于正常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆