PostgreSQLにタイムゾーン対応のtimestamptz
フィールドがあります。テーブルからデータを取得するとき、その時点の時間を取得できるように、今すぐ時間を減算したいです。
私が抱えている問題は、datetime.datetime.now()
とdatetime.datetime.utcnow()
の両方がタイムゾーンを認識しないタイムスタンプを返すようであるため、このエラーが発生することです:
TypeError: can't subtract offset-naive and offset-aware datetimes
これを回避する方法はありますか(できればサードパーティのモジュールを使用しないで)。
編集:提案に感謝しますが、タイムゾーンを調整しようとするとエラーが発生するようです。したがって、PGでタイムゾーンを認識しないタイムスタンプを使用し、常に次のものを使用して挿入します。
NOW() AT TIME ZONE 'UTC'
そうすれば、私のタイムスタンプはすべてデフォルトでUTCになります(これを行うのはもっと面倒ですが)。
タイムゾーン認識を削除しようとしましたか?
from http://pytz.sourceforge.net/
naive = dt.replace(tzinfo=None)
タイムゾーンの変換も追加する必要があります。
編集:この答えの年齢に注意してください。 Python 3の回答は次のとおりです。
正しい解決策は、addタイムゾーン情報です。たとえば、Python 3の認識された日時オブジェクトとして現在の時刻を取得します。
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)
この種のデータベース相互作用を抽象化するためのインターフェイスとしてDjangoを使用する人がいることは知っています。 Djangoは、これに使用できるユーティリティを提供します。
from Django.utils import timezone
now_aware = timezone.now()
このタイプのインターフェイスを使用しているだけでも、基本的なDjango設定インフラストラクチャを設定する必要があります(設定では、USE_TZ=True
を含めて日時を取得する必要があります)。
これだけでは、おそらくDjangoをインターフェイスとして使用するように動機づけるのに十分ではありませんが、他にも多くの特典があります。一方、Djangoアプリをマングルしていたためにここでつまずいた場合は(おそらく私がしたように)、おそらくこれが役立ちます...
これは非常にシンプルで明確なソリューションです
2行のコード
# 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
同じ時刻情報で日時変数を管理する必要があります
Psycopg2モジュールには独自のタイムゾーン定義があるため、最終的にutcnowのラッパーを作成しました。
def pg_utcnow():
import psycopg2
return datetime.utcnow().replace(
tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=0, name=None))
postgreSQL timestamptz
と比較するために現在の時刻が必要なときはいつでもpg_utcnow
を使用するだけです
私も同じ問題に直面しました。それから私は多くの検索の後に解決策を見つけました。
問題は、モデルまたはフォームからdatetimeオブジェクトを取得するときはオフセット対応であり、システムで時刻を取得する場合はオフセットナイーブであるということでした。
だから私はtimezone.now()を使用して現在の時間を取得し、Django.utils import timezoneでタイムゾーンをインポートし、SE_TZ = Trueプロジェクト設定ファイル。
私は非常にシンプルなソリューションを思い付きました:
import datetime
def calcEpochSec(dt):
epochZero = datetime.datetime(1970,1,1,tzinfo = dt.tzinfo)
return (dt - epochZero).total_seconds()
タイムゾーン対応およびタイムゾーン未処理の日時値の両方で機能します。また、追加のライブラリやデータベースの回避策は不要です。
PostgreSQL自体で年齢の計算を処理できます。何かのようなもの
select *, age(timeStampField) as timeStampAge from myTable
timezone.make_aware(datetime.datetime.now())
がDjangoで役立つことがわかりました(1.9.1を使用しています)。残念ながら、単にdatetime
オブジェクトをオフセット対応にしてからtimetz()
にすることはできません。 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 :-(')