Created
June 9, 2020 13:56
-
-
Save afonasev/9e0a21a6437697a4604b6e22ab7682c3 to your computer and use it in GitHub Desktop.
UTCDateTime field for sqlalchemy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from datetime import timezone | |
import sqlalchemy as sa | |
class UTCDateTime(sa.TypeDecorator): # pylint:disable=W0223 | |
"""By default if we provide datetime object without timezone Postgres applies | |
his timezone to that datetime. To prevent unexpected behaviour we add utc timezone | |
before every write. And convert back to utc, after every read. | |
From PostgreSQL docs: | |
For timestamp with time zone, the internally stored value is always in UTC. | |
An input value that has an explicit time zone specified is converted to UTC | |
using the appropriate offset for that time zone. If no time zone is stated | |
in the input string, then it is assumed to be in the time zone indicated | |
by the system's timezone parameter, and is converted to UTC using the offset | |
for the timezone zone. | |
When a timestamp with time zone value is output, it is always converted from UTC | |
to the current timezone zone, and displayed as local time in that zone. | |
""" | |
impl = sa.DateTime | |
def process_bind_param(self, value, dialect): | |
"""Way into the database. | |
Convert datetime to utc timezone, with tzinfo=timezone.utc, so | |
Postgres doesnt apply his own timezone | |
""" | |
if value is not None: | |
if not value.tzinfo: | |
value = value.replace(tzinfo=timezone.utc) | |
return value.astimezone(timezone.utc) | |
return None | |
def process_result_value(self, value, dialect): | |
"""Way out of the database. | |
Here we receive datetime with Postgres timezone and convert to UTC, | |
then replace timezone with None | |
""" | |
if value: | |
return value.astimezone(timezone.utc).replace(tzinfo=None) | |
return None |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment