2009-01-05 17 views
35

SQLAlchemy's DateTime türü, nakil olmayan bir datetime nesnesini veritabanına kaydetmek ve bu şekilde döndürmek için timezone=True bağımsız değişkenine izin verir. tzinfo'un saat dilimini değiştirmek için SQLAlchemy'nin örneğin UTC gibi olabilmesi için herhangi bir yolu var mı? default=datetime.datetime.utcnow'u kullanabileceğimin farkındayım; bununla birlikte, naif bir yerel zaman çizelgesine dayanan bir tarihte geçen birini mutlu bir şekilde kabul edebilecek bir naif bir zamandır, bununla birlikte timezone=True kullansaydım bile, normal ya da UTC zamanını, normalize etmek için bir taban zaman dilimi kullanmadan naif yapar. Datetime nesnesini naif olmayan yapmak için (pytz kullanarak) denedim, ancak bunu DB'ye kaydettiğimde, naif olarak geri geliyor. datetime.datetime.utcnow çok iyi timezone=True çalışmaz nasılSQLAlchemy DateTime zaman dilimi

Not:

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

metadata = sa.MetaData('postgres://user:[email protected]/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, datetime.datetime (2009, 1, 6, 0, 9, 36, 891.887)) benim localtime dengeleniyor

row[1].utcoffset() 

datetime.timedelta (-1, 64800) # !!

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

datetime.timedelta (-1, 64800)

datetime.timedelta (0) #UTC

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

bunu değiştirmek bile UTC'yi açıkça kullanmak için:

...

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) o zaman dilimini kullanmak vermedi # açıkça

Ya düşerse eklendi 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 

...

Gerçek # bile db bir saat dilimi bu kez

cevap

17

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

Tüm zaman dilimi farkında tarihler ve saatler kurtaramadı saklanır UTC içinde dahili olarak. İstemciye görüntülenmeden önce, saat dilimi yapılandırma parametresi tarafından belirtilen bölgede yerel saate dönüştürülür.

Postgresql ile saklamanın tek yolu, ayrı ayrı saklamaktır.

+0

"Zaman dilimi yapılandırma parametresi", depolanan veritabanındaki datetime_with_timzone'daki saat dilimi bilgisidir? –

+1

@Ciastopiekarz Hayır. 'Timezone' yapılandırma parametresi bir istemci bağlantı parametresidir. Değeri UTC'de saklanan "saat dilimine sahip tarihsaat", bu "saat dilimi" parametresinde belirtilen görüntüyü size göstermeden veya döndürmeden önce dönüştürülür. Geçerli bağlantınız için hangi değerin olduğunu kontrol etmek için 'SHOW timezone'unu kullanın. Gerçekten neye ihtiyacınız olduğunu bir düşünün: Bir olayın meydana geldiği zamanı saklamak mı gerekiyor yoksa depolanmış veri uzunluğu değerinin gerçekte hangi saat diliminde kaynaklandığı da kaydedilmeli mi? İkincisi ise, bu bilgiyi ayrı ayrı saklamanız gerekir. – compostus

+0

Sadece ne zaman gerçekleştiğini, ancak UTC'de, muhtemelen mevcut bağlantıyı bildiğim zaman, zaman dilimi bilgisi olmadan, kullanıcının tam olarak ne zaman doğru bir olay meydana geldiğini bilmeyeceğim. –

5

bir çözüm this question’s cevap verilmiştir:

Eğer UTC veritabanındaki tüm (tarih) zaman nesneleri depolamak ve alma üzerine haberdar olanlar için çıkan naif tarih saat nesneleri dönüştürerek bu asabilirsiniz.

tek dezavantajı, zaman dilimi bilgilerini kaybetmemenizdir, ancak, datetime nesnelerini utc'de saklamak muhtemelen iyi bir fikirdir.

Eğer zaman dilimi bilgi veriyorsan

ya da belki gerek yok, ben ayrı bir yerde saklayın ediyorum ve sadece (örneğin sağ görüntülemeden önce) mümkün olan son durumda yerel saate utc dönüştürmek Her şeyden önemlisi, progamınızı çalıştırdığınız makineden yerel saat dilimi bilgilerini veya bir web uygulamasıysa kullanıcının tarayıcısını kullanabilir.

+0

saat dilimi bilgilerini kaybedersek, ancak tarih/saati UTC'ye kaydedebilirsek, tarih saatini timinone ile "timestamptz" yerine "string" türünde tanımlanmış bir sütuna neden kaydetmeziz? –