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 object in the DB without tying myself to a specific database? Right now, I'm making sure that times are UTC before I store them in the DB, and converting to localized at display-time, but that feels inelegant and brittle. Is there a DB-agnostic way to get a timezone-aware datetime out of SQLAlchemy instead of getting naive datatime objects out of the DB?
+3
A:
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 dateutil.tz import tzutc
from datetime import datetime
class UTCDateTime(types.TypeDecorator):
impl = types.DateTime
def process_bind_param(self, value, engine):
if value is not None:
return value.astimezone(tzutc())
def process_result_value(self, value, engine):
if value is not None:
return datetime(value.year, value.month, value.day,
value.hour, value.minute, value.second,
value.microsecond, tzinfo=tzutc())
Note, that is behaves nicely when you use naive datetime
by accident.
Denis Otkidach
2010-03-27 07:01:27
This doesn't work as written, it needs a minor tweak in `process_bind_param`: `def process_bind_param(self, value, engine):\n if value is not None:\n if value.tzinfo is None:\n return value.replace(tzinfo=tzutc())\n else:\n return value.astimezone(tzutc())`
Jesse Dhillon
2010-08-01 08:03:37
@Jesse Dhillon: it's intentional to prevent accidental storage of naive datetime objects, while your recipe incorrectly inteprets any datetime with any timezone as being UTC.
Denis Otkidach
2010-08-04 03:35:02
@Dennis, so using your type, one is expected to create and store only timezone-aware `datetime` objects? Now that I understand that, I like your solution more because it requires the user to be explicit about what they are saving.
Jesse Dhillon
2010-08-04 05:37:33