我在PostgreSQL中有一个时区感知timestamptz字段。当我从表中提取数据时,我想减去现在的时间,这样我就可以得到它的年龄。
我遇到的问题是datetime.datetime.now()和datetime.datetime.utcnow()似乎都返回不知道时区的时间戳,这导致我得到这个错误:
TypeError: can't subtract offset-naive and offset-aware datetimes
是否有办法避免这种情况(最好不使用第三方模块)。
编辑:谢谢你的建议,但试图调整时区似乎给我错误。所以我将在PG中使用不考虑时区的时间戳,并且总是插入using:
NOW() AT TIME ZONE 'UTC'
这样,默认情况下我的所有时间戳都是UTC(尽管这样做更烦人)。
我知道这是旧的,但我只是想加上我的解决方案,以防有人发现它有用。
我想比较本地天真datetime和时间服务器上的感知datetime。我基本上使用感知datetime对象创建了一个新的朴素datetime对象。这是一个有点hack,看起来不太漂亮,但可以完成工作。
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 :-(')
正确的解决方案是添加时区信息,例如,在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)
你不需要性病资料库以外的任何东西
datetime.datetime.now().astimezone()
如果你只是更换了时区,它不会调整时间。如果你的系统已经是UTC,那么.replace(tz='UTC')就可以了。
>>> x=datetime.datetime.now()
datetime.datetime(2020, 11, 16, 7, 57, 5, 364576)
>>> print(x)
2020-11-16 07:57:05.364576
>>> print(x.astimezone())
2020-11-16 07:57:05.364576-07:00
>>> print(x.replace(tzinfo=datetime.timezone.utc)) # wrong
2020-11-16 07:57:05.364576+00:00