SQLAlchemy DateTime ζώνη ώρας

ψήφοι
35

SQLAlchemy του DateTimeτύπου επιτρέπει ένα timezone=Trueεπιχείρημα για να σώσει ένα μη-αφελή αντικείμενο datetime στη βάση δεδομένων και να το επιστρέψει ως τέτοια. Υπάρχει κάποιος τρόπος για να τροποποιήσετε τη ζώνη ώρας του tzinfoότι SQLAlchemy περνάει έτσι θα μπορούσε να είναι, για παράδειγμα, 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, datetime.datetime (2009, 1, 6, 0, 9, 36, 891887))

row[1].utcoffset()

datetime.timedelta (-1, 64800) # που είναι offset localtime μου !!

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

...

Αληθινή # δεν είχε καν να σώσει μια ζώνη ώρας στην db αυτή τη φορά

Δημοσιεύθηκε 05/01/2009 στις 22:46
πηγή χρήστη
Σε άλλες γλώσσες...                            


3 απαντήσεις

ψήφοι
17

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

Όλα ζώνη ώρας με επίγνωση ημερομηνίες και ώρες που αποθηκεύονται εσωτερικά σε UTC. Είναι μετατρέπεται σε τοπική ώρα στη ζώνη που ορίζεται από την παράμετρο ρύθμισης ζώνης ώρας πριν εμφανιστούν στον πελάτη.

Ο μόνος τρόπος για να το αποθηκεύσετε με PostgreSQL είναι να το αποθηκεύσετε ξεχωριστά.

Απαντήθηκε 20/01/2009 στις 15:24
πηγή χρήστη

ψήφοι
5

μια λύση δίνεται σε αυτό το ερώτημα είναι απάντηση:

μπορείτε να παρακάμψουν ότι με την αποθήκευση όλων των αντικειμένων (ημερομηνία) ώρα στη βάση δεδομένων σας σε UTC, και τη μετατροπή τους που απορρέουν αφελείς αντικείμενα datetime να γνωρίζουν αυτές που αφορούν την ανάκτηση.

το μόνο μειονέκτημα είναι ότι θα χάσετε τη ζώνη ώρας πληροφορίες, αλλά είναι πιθανώς μια καλή ιδέα να αποθηκεύετε αντικείμενα datetime σας σε UTC, ούτως ή άλλως.

αν σας ενδιαφέρει σχετικά με τις πληροφορίες ζώνης ώρας, θα ήθελα να αποθηκεύουν ξεχωριστά, και να μετατρέψει μόνο την UTC στην τοπική ώρα στο τελευταίο δυνατό βαθμό (π.χ. δικαίωμα πριν από την εμφάνιση)

ή ίσως δεν χρειάζεται να φροντίζουν μετά από όλα, και μπορεί να χρησιμοποιήσει τις τοπικές πληροφορίες ζώνης ώρας από το μηχάνημα που τρέχει progam σας ή το πρόγραμμα περιήγησης του χρήστη αν είναι μια εφαρμογή ιστού.

Απαντήθηκε 02/10/2012 στις 16:16
πηγή χρήστη

ψήφοι
0

Ένας τρόπος για να λυθεί αυτό το ζήτημα είναι να χρησιμοποιείτε πάντα τη ζώνη ώρας με επίγνωση πεδία στη βάση δεδομένων. Αλλά σημειώνει ότι την ίδια στιγμή μπορεί να εκφραστεί με διαφορετικό τρόπο ανάλογα με τη ζώνη ώρας, ακόμα και αν αυτό δεν είναι ένα πρόβλημα για τους υπολογιστές είναι πολύ ενοχλητικό για μας:

2003-04-12 23:05:06 +01:00
2003-04-13 00:05:06 +02:00 # This is the same time as above!

Επίσης Postgresql αποθηκεύει όλες ζώνη ώρας με επίγνωση ημερομηνίες και ώρες εσωτερικά σε UTC. Είναι μετατρέπεται σε τοπική ώρα στη ζώνη που ορίζεται από την παράμετρο ρύθμισης ζώνης ώρας πριν εμφανιστούν στον πελάτη.

Αντ 'αυτού, ήθελα να συστήσω τη χρήση UTCχρονικές σημάνσεις και σε όλη την εφαρμογή και τη ζώνη ώρας, αφελής ημερομηνίες και ώρες στη βάση δεδομένων, και τη μετατροπή τους μόνο σε χρήστες με την τοπική ώρα πριν από το χρήστη να βλέπει.

Η στρατηγική αυτή σας επιτρέπει να έχουν την πιο καθαρή κώδικα, αποφεύγοντας τυχόν μετατροπές ζώνη ώρας και συγχύσεις, και κάνει βάσης δεδομένων και εφαρμογών δουλειά σας με συνέπεια ανεξάρτητα από τις διαφορές «τοπική ώρα». Για παράδειγμα, μπορεί να έχετε μηχανή ανάπτυξης και διακομιστή παραγωγής που λειτουργούν με σύννεφο σε διαφορετικές ζώνες ώρας.

Για να επιτευχθεί αυτό, πείτε Postgresql ότι θέλετε να δείτε ζώνες ώρας σε UTC πριν από την προετοιμασία του κινητήρα.

Σε SqlAlchemy μπορείτε να το κάνετε ως εξής:

engine = create_engine(..., connect_args={"options": "-c timezone=utc"})

Και αν χρησιμοποιείτε ανεμοστρόβιλος-sqlalchemy που μπορείτε να χρησιμοποιήσετε:

factory = make_session_factory(..., connect_args={"options": "-c timezone=utc"})

Δεδομένου ότι χρησιμοποιούμε όλες τις ζώνες ώρας UTC παντού, εμείς απλά χρησιμοποιήστε ζώνη ώρας-αφελής ημερομηνίες και ώρες στο μοντέλο:

created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime)

Και το ίδιο σε περίπτωση που χρησιμοποιείτε άμβυκα:

sa.Column('created_at', sa.DateTime()),
sa.Column('updated_at', sa.DateTime()),

Και στην εποχή κωδικό χρήση UTC:

from datetime import datetime
...
model_object.updated_at = datetime.now(timezone.utc)
Απαντήθηκε 27/01/2020 στις 15:16
πηγή χρήστη

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more