57

SQLAlchemy のDateTime型では、timezone=True引数を使用して、naive でない datetime オブジェクトをデータベースに保存し、そのまま返すことができます。SQLAlchemy が渡すタイムゾーンを変更してtzinfo、たとえば UTC にする方法はありますか? を使用できることに気づきましたdefault=datetime.datetime.utcnow。ただし、これは単純な localtime ベースの datetime を渡す人を喜んで受け入れる単純な時間です。これを使用timezone=Trueしたとしても、正規化するベース タイムゾーンがなくてもローカル時間または UTC 時間が非単純になるためです。( pytzを使用して) datetime オブジェクトを非ナイーブにしようとしましたが、これを DB に保存すると、ナイーブとして返されます。

datetime.datetime.utcnow がうまく機能しないことに注意してくださいtimezone=True

import sqlalchemy as sa
from sqlalchemy.sql import select
import datetime

metadata = sa.MetaData('postgres://user:pass@machine/db')

data_table = sa.Table('data', metadata,
    sa.Column('id',   sa.types.Integer, primary_key=True),
    sa.Column('date', sa.types.DateTime(timezone=True), default=datetime.datetime.utcnow)
)

metadata.create_all()

engine = metadata.bind
conn = engine.connect()
result = conn.execute(data_table.insert().values(id=1))

s = select([data_table])
result = conn.execute(s)
row = result.fetchone()

(1, 日時.日時(2009, 1, 6, 0, 9, 36, 891887))

row[1].utcoffset()

datetime.timedelta(-1, 64800) # これが私の現地時間オフセットです!!

datetime.datetime.now(tz=pytz.timezone("US/Central"))

datetime.timedelta(-1, 64800)

datetime.datetime.now(tz=pytz.timezone("UTC"))

datetime.timedelta(0) #UTC

明示的に UTC を使用するように変更しても:

...

data_table = sa.Table('data', metadata,
    sa.Column('id',   sa.types.Integer, primary_key=True),
    sa.Column('date', sa.types.DateTime(timezone=True), default=datetime.datetime.now(tz=pytz.timezone('UTC')))
)

row[1].utcoffset()

...

datetime.timedelta(-1, 64800) # 明示的に追加したタイムゾーンを使用していませんでした

または、ドロップするとtimezone=True:

...

data_table = sa.Table('data', metadata,
    sa.Column('id',   sa.types.Integer, primary_key=True),
    sa.Column('date', sa.types.DateTime(), default=datetime.datetime.now(tz=pytz.timezone('UTC')))
)

row[1].utcoffset() is None

...

True # 今回はタイムゾーンをデータベースに保存しませんでした

4

4 に答える 4

28

http://www.postgresql.org/docs/8.3/interactive/datatype-datetime.html#DATATYPE-TIMEZONES

すべてのタイムゾーン対応の日付と時刻は、UTC で内部的に保存されます。クライアントに表示される前に、timezone 構成パラメーターで指定されたゾーンの現地時間に変換されます。

postgresql で保存する唯一の方法は、個別に保存することです。

于 2009-01-20T16:24:22.457 に答える
10

この質問の回答に解決策が示されています。

データベース内のすべての (日付) 時刻オブジェクトを UTC で保存し、結果の単純な datetime オブジェクトを取得時に認識できるものに変換することで、これを回避できます。

唯一の欠点は、タイムゾーン情報が失われることですが、とにかく、datetime オブジェクトを utc に格納することをお勧めします。

タイムゾーン情報が気になる場合は、それを個別に保存し、可能な最後のインスタンス(表示の直前など)でのみutcを現地時間に変換します

または、結局気にする必要はなく、プログラムを実行しているマシン、または webapp の場合はユーザーのブラウザーからのローカル タイムゾーン情報を使用できます。

于 2012-10-02T17:16:57.690 に答える