# ruff: noqa: FA100
import datetime
from typing import Optional
from sqlalchemy import DateTime
from sqlalchemy.engine import Dialect
from sqlalchemy.types import TypeDecorator
__all__ = ("DateTimeUTC",)
[docs]
class DateTimeUTC(TypeDecorator[datetime.datetime]):
"""Timezone Aware DateTime.
Ensure UTC is stored in the database and that TZ aware dates are returned for all dialects.
"""
impl = DateTime(timezone=True)
cache_ok = True
@property
def python_type(self) -> type[datetime.datetime]:
return datetime.datetime
[docs]
def process_bind_param(self, value: Optional[datetime.datetime], dialect: Dialect) -> Optional[datetime.datetime]:
if value is None:
return value
if not value.tzinfo:
msg = "tzinfo is required"
raise TypeError(msg)
return value.astimezone(datetime.timezone.utc)
[docs]
def process_result_value(self, value: Optional[datetime.datetime], dialect: Dialect) -> Optional[datetime.datetime]:
if value is None:
return value
if value.tzinfo is None:
return value.replace(tzinfo=datetime.timezone.utc)
return value