Can Sqlalchemy Datetime Objects Only Be Naive?
I am working with SQLAlchemy, and I'm not yet sure which database I'll use under it, so I want to remain as DB-agnostic as possible. How can I store a timezone-aware datetime obje
Solution 1:
There is a timezone
parameter to DateTime
column time, so there is no problem with storing timezone-aware datetime
objects. However I found convenient to convert stored datetime
to UTC automatically with simple type decorator:
from sqlalchemy import types
from datetime import datetime, timezone
classUTCDateTime(types.TypeDecorator):
impl = types.DateTime
defprocess_bind_param(self, value, engine):
if value isNone:
returnif value.utcoffset() isNone:
raise ValueError(
'Got naive datetime while timezone-aware is expected'
)
return value.astimezone(timezone.utc)
defprocess_result_value(self, value, engine):
if value isnotNone:
return value.replace(tzinfo=timezone.utc)
Note, that is behaves nicely when you use naive datetime
by accident (meaning it will raise a ValueError).
Solution 2:
I am addressing the desire to have datetime-aware in my code by using UTC in all internal instances. The only issue I came up with was when reading the database. Despite writing datetime-aware to the database, when retrieving the format is naive. My fix was:
importpytzdt= mydb.query.filter_by(name='test').first().last_update.replace(tzinfo=pytz.utc)
dt
is the variable that will store the last_update retrieved in datetime formatmydb
is the name of my db tablename
is one of the columns in the tablelast_update
is a column that is stored in the format datetime
The trick is replace(tzinfo=pytz.utc)
Solution 3:
The SQLAlchemy documentation has a recipe for this:
import datetime
classTZDateTime(TypeDecorator):
impl = DateTime
defprocess_bind_param(self, value, dialect):
if value isnotNone:
ifnot value.tzinfo:
raise TypeError("tzinfo is required")
value = value.astimezone(datetime.timezone.utc).replace(
tzinfo=None
)
return value
defprocess_result_value(self, value, dialect):
if value isnotNone:
value = value.replace(tzinfo=datetime.timezone.utc)
return value
Post a Comment for "Can Sqlalchemy Datetime Objects Only Be Naive?"