标签归档:postgresql

无法减去天真偏移和可感知偏移的日期时间

问题:无法减去天真偏移和可感知偏移的日期时间

timestamptz在PostgreSQL中有一个时区识别字段。当我从表中提取数据时,我想现在减去时间,以便确定时间。

我遇到的问题是,无论是datetime.datetime.now()datetime.datetime.utcnow()似乎回到时区不知道时间戳,这导致我得到这个错误:

TypeError: can't subtract offset-naive and offset-aware datetimes 

有没有一种方法可以避免这种情况(最好不要使用第三方模块)。

编辑:感谢您的建议,但是尝试调整时区似乎给了我错误..所以我只打算在PG中使用不知道时区的时间戳,并始终使用以下命令插入:

NOW() AT TIME ZONE 'UTC'

这样,默认情况下,我所有的时间戳都是UTC(即使这样做比较烦人)。

I have a timezone aware timestamptz field in PostgreSQL. When I pull data from the table, I then want to subtract the time right now so I can get it’s age.

The problem I’m having is that both datetime.datetime.now() and datetime.datetime.utcnow() seem to return timezone unaware timestamps, which results in me getting this error:

TypeError: can't subtract offset-naive and offset-aware datetimes 

Is there a way to avoid this (preferably without a third-party module being used).

EDIT: Thanks for the suggestions, however trying to adjust the timezone seems to give me errors.. so I’m just going to use timezone unaware timestamps in PG and always insert using:

NOW() AT TIME ZONE 'UTC'

That way all my timestamps are UTC by default (even though it’s more annoying to do this).


回答 0

您是否尝试删除时区意识?

来自http://pytz.sourceforge.net/

naive = dt.replace(tzinfo=None)

可能还必须添加时区转换。

编辑:请注意这个答案的年龄。以下是Python 3的答案。

have you tried to remove the timezone awareness?

from http://pytz.sourceforge.net/

naive = dt.replace(tzinfo=None)

may have to add time zone conversion as well.

edit: Please be aware the age of this answer. An answer involving ADDing the timezone info instead of removing it in python 3 is below. https://stackoverflow.com/a/25662061/93380


回答 1

正确的解决方案是添加时区信息,例如,将当前时间作为Python 3中已知的datetime对象获取:

from datetime import datetime, timezone

now = datetime.now(timezone.utc)

在较旧的Python版本上,您可以utc自己定义tzinfo对象(例如datetime docs中的示例):

from datetime import tzinfo, timedelta, datetime

ZERO = timedelta(0)

class UTC(tzinfo):
  def utcoffset(self, dt):
    return ZERO
  def tzname(self, dt):
    return "UTC"
  def dst(self, dt):
    return ZERO

utc = UTC()

然后:

now = datetime.now(utc)

The correct solution is to add the timezone info e.g., to get the current time as an aware datetime object in Python 3:

from datetime import datetime, timezone

now = datetime.now(timezone.utc)

On older Python versions, you could define the utc tzinfo object yourself (example from datetime docs):

from datetime import tzinfo, timedelta, datetime

ZERO = timedelta(0)

class UTC(tzinfo):
  def utcoffset(self, dt):
    return ZERO
  def tzname(self, dt):
    return "UTC"
  def dst(self, dt):
    return ZERO

utc = UTC()

then:

now = datetime.now(utc)

回答 2

我知道有人专门使用Django作为抽象此类数据库交互的接口。Django提供了可用于此目的的实用程序:

from django.utils import timezone
now_aware = timezone.now()

您确实需要设置基本的Django设置基础结构,即使您只是使用这种类型的界面(在设置中,也需要包括在内USE_TZ=True以获取已知的日期时间)。

就其本身而言,这可能还远远不足以激发您使用Django作为界面,但是还有许多其他好处。另一方面,如果您是因为要破坏Django应用(如我所做的那样)而在这里偶然发现的,那么这可能会有所帮助…

I know some people use Django specifically as an interface to abstract this type of database interaction. Django provides utilities that can be used for this:

from django.utils import timezone
now_aware = timezone.now()

You do need to set up a basic Django settings infrastructure, even if you are just using this type of interface (in settings, you need to include USE_TZ=True to get an aware datetime).

By itself, this is probably nowhere near enough to motivate you to use Django as an interface, but there are many other perks. On the other hand, if you stumbled here because you were mangling your Django app (as I did), then perhaps this helps…


回答 3

这是一个非常简单明了的解决方案
两行代码

# First we obtain de timezone info o some datatime variable    

tz_info = your_timezone_aware_variable.tzinfo

# Now we can subtract two variables using the same time zone info
# For instance
# Lets obtain the Now() datetime but for the tz_info we got before

diff = datetime.datetime.now(tz_info)-your_timezone_aware_variable

结论:您必须使用相同的时间信息来管理日期时间变量

This is a very simple and clear solution
Two lines of code

# First we obtain de timezone info o some datatime variable    

tz_info = your_timezone_aware_variable.tzinfo

# Now we can subtract two variables using the same time zone info
# For instance
# Lets obtain the Now() datetime but for the tz_info we got before

diff = datetime.datetime.now(tz_info)-your_timezone_aware_variable

Conclusion: You must mange your datetime variables with the same time info


回答 4

psycopg2模块具有自己的时区定义,因此我最终围绕utcnow编写了自己的包装器:

def pg_utcnow():
    import psycopg2
    return datetime.utcnow().replace(
        tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=0, name=None))

并且只pg_utcnow在需要当前时间与PostgreSQL比较时使用timestamptz

The psycopg2 module has its own timezone definitions, so I ended up writing my own wrapper around utcnow:

def pg_utcnow():
    import psycopg2
    return datetime.utcnow().replace(
        tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=0, name=None))

and just use pg_utcnow whenever you need the current time to compare against a PostgreSQL timestamptz


回答 5

我也面临同样的问题。经过大量搜索之后,我找到了解决方案。

问题是,当我们从模型或表单获取datetime对象时,它是偏移量感知的;如果通过系统获取时间,则它是偏移量天真的

所以我要做的是使用timezone.now()获得当前时间,并从django.utils import timezone导入时区,并将USE_TZ = True放入项目设置文件中。

I also faced the same problem. Then I found a solution after a lot of searching .

The problem was that when we get the datetime object from model or form it is offset aware and if we get the time by system it is offset naive.

So what I did is I got the current time using timezone.now() and import the timezone by from django.utils import timezone and put the USE_TZ = True in your project settings file.


回答 6

我想出了一个超简单的解决方案:

import datetime

def calcEpochSec(dt):
    epochZero = datetime.datetime(1970,1,1,tzinfo = dt.tzinfo)
    return (dt - epochZero).total_seconds()

它适用于时区感知和时区原始日期时间值。并且不需要其他库或数据库解决方法。

I came up with an ultra-simple solution:

import datetime

def calcEpochSec(dt):
    epochZero = datetime.datetime(1970,1,1,tzinfo = dt.tzinfo)
    return (dt - epochZero).total_seconds()

It works with both timezone-aware and timezone-naive datetime values. And no additional libraries or database workarounds are required.


回答 7

我发现timezone.make_aware(datetime.datetime.now())在Django中很有帮助(我在1.9.1上)。不幸的是,您不能简单地使datetime对象具有偏移意识timetz()。您必须做一个,datetime并在此基础上进行比较。

I’ve found timezone.make_aware(datetime.datetime.now()) is helpful in django (I’m on 1.9.1). Unfortunately you can’t simply make a datetime object offset-aware, then timetz() it. You have to make a datetime and make comparisons based on that.


回答 8

有一些紧迫的原因导致您无法在PostgreSQL本身中处理年龄计算吗?就像是

select *, age(timeStampField) as timeStampAge from myTable

Is there some pressing reason why you can’t handle the age calculation in PostgreSQL itself? Something like

select *, age(timeStampField) as timeStampAge from myTable

回答 9

我知道这很旧,但只是想我会添加我的解决方案,以防万一有人觉得有用。

我想将本地原始日期时间与时间服务器的已知日期时间进行比较。我基本上使用感知的datetime对象创建了一个新的朴素的datetime对象。这有点骇人听闻,看起来并不漂亮,但是可以完成工作。

import ntplib
import datetime
from datetime import timezone

def utc_to_local(utc_dt):
    return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)    

try:
    ntpt = ntplib.NTPClient()
    response = ntpt.request('pool.ntp.org')
    date = utc_to_local(datetime.datetime.utcfromtimestamp(response.tx_time))
    sysdate = datetime.datetime.now()

…软糖来了…

    temp_date = datetime.datetime(int(str(date)[:4]),int(str(date)[5:7]),int(str(date)[8:10]),int(str(date)[11:13]),int(str(date)[14:16]),int(str(date)[17:19]))
    dt_delta = temp_date-sysdate
except Exception:
    print('Something went wrong :-(')

I know this is old, but just thought I would add my solution just in case someone finds it useful.

I wanted to compare the local naive datetime with an aware datetime from a timeserver. I basically created a new naive datetime object using the aware datetime object. It’s a bit of a hack and doesn’t look very pretty but gets the job done.

import ntplib
import datetime
from datetime import timezone

def utc_to_local(utc_dt):
    return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)    

try:
    ntpt = ntplib.NTPClient()
    response = ntpt.request('pool.ntp.org')
    date = utc_to_local(datetime.datetime.utcfromtimestamp(response.tx_time))
    sysdate = datetime.datetime.now()

…here comes the fudge…

    temp_date = datetime.datetime(int(str(date)[:4]),int(str(date)[5:7]),int(str(date)[8:10]),int(str(date)[11:13]),int(str(date)[14:16]),int(str(date)[17:19]))
    dt_delta = temp_date-sysdate
except Exception:
    print('Something went wrong :-(')

Redash-让您的公司实现数据驱动。连接到任何数据源,轻松可视化、控制面板和共享您的数据

Redash旨在让任何人,无论技术复杂程度如何,都能利用大大小小数据的力量。SQL用户可以利用Redash来浏览、查询、可视化和共享来自任何数据源的数据。反过来,他们的工作使其组织中的任何人都可以使用这些数据。每天,世界各地数千个组织的数百万用户使用Redash开发洞察力并做出数据驱动的决策

Redash功能:

  1. 基于浏览器:浏览器中的所有内容,都有可共享的URL
  2. 易用性:立即利用数据提高工作效率,无需掌握复杂的软件
  3. 查询编辑器:使用架构浏览器和自动完成功能快速编写SQL和NoSQL查询
  4. 可视化和控制面板:创建beautiful visualizations拖放,并将它们组合到单个仪表板中
  5. 共享:通过共享可视化及其相关查询轻松协作,实现报告和查询的同行审查
  6. 计划刷新:按您定义的定期间隔自动更新图表和仪表板
  7. 警报:定义条件,并在数据更改时立即发出警报
  8. 睡觉接口:UI中可以做的一切也通过睡觉接口提供
  9. 对数据源的广泛支持:可扩展的数据源API,具有对一长串常用数据库和平台的本机支持

快速入门

支持的数据源

Redash支持超过35个SQL和NoSQLdata sources它还可以扩展以支持更多内容。以下是内置源的列表:

  • 亚马逊雅典娜
  • Amazon DynamoDB
  • 亚马逊红移
  • Axibase时间序列数据库
  • 卡桑德拉
  • ClickHouse
  • CockroachDB
  • CSV
  • 数据库(阿帕奇电光)
  • IBM的DB2
  • 德鲁伊
  • ES
  • 谷歌分析
  • Google BigQuery
  • 谷歌电子表格
  • 石墨
  • 绿梅
  • Hive
  • 黑斑羚
  • InfluxDB
  • JIRA
  • JSON
  • 阿帕奇麒麟
  • OmniSciDB(前身为MAPD)
  • MemSQL
  • Microsoft Azure数据仓库/Synapse
  • Microsoft Azure SQL数据库
  • Microsoft SQL Server
  • MongoDB
  • MySQL
  • 甲骨文
  • PostgreSQL
  • 普罗米修斯
  • python
  • 夸博尔
  • 岩石集
  • Salesforce
  • ScyllaDB
  • Shell脚本
  • 雪花
  • SQLite
  • TiDB
  • 财务数据
  • 垂直方向
  • Yandex AppMetrrica
  • Yandex Metrica

获取帮助

报告错误和贡献代码

  • 想要报告错误或请求功能吗?请打开an issue
  • 想要帮助我们建造雷达什?分叉项目,在dev environment并提出拉取请求。我们需要所有能得到的帮助!

安全性

请发电子邮件给我security@redash.io报告任何安全漏洞。我们将确认收到您的漏洞,并努力定期向您发送有关我们进度的最新信息。如果您对您的信息披露情况感到好奇,请随时再次向我们发送电子邮件。如果您想要加密您的披露电子邮件,您可以使用this PGP key

许可证

BSD-2-条款