Summary
DateTimeUTC currently wraps DateTime(timezone=True). On MySQL it compiles to DATETIME (effectively DATETIME(0)), and on Oracle it compiles to DATE. Those types do not preserve fractional seconds.
This matters for timestamps used in expiry or lease comparisons: a value such as now + timedelta(milliseconds=50) is quantized to a whole second. Depending on the current fractional second, the stored deadline can expire too early or remain live hundreds of milliseconds too long.
MCVE
from advanced_alchemy.types import DateTimeUTC
from sqlalchemy.dialects import mysql, oracle
timestamp = DateTimeUTC()
print(timestamp.compile(dialect=mysql.dialect()))
print(timestamp.compile(dialect=oracle.dialect()))
Current output:
On MySQL, a test that stores a 50 ms expiry, waits 200 ms, and then evaluates expires_at <= now fails intermittently based on the acquisition time's fractional second. Compiling the column as DATETIME(6) makes the same test deterministic while retaining microseconds.
Compatibility-safe direction
A non-breaking option would be to add an opt-in precision argument, for example DateTimeUTC(fsp=6), while preserving today's DDL when the argument is omitted. The opt-in path could use:
- MySQL/MariaDB:
mysql.DATETIME(fsp=6)
- Oracle:
oracle.TIMESTAMP
- Existing generic timezone-aware
DateTime behavior elsewhere
A separate precise UTC timestamp type would also avoid changing existing schemas. Either approach would let applications request precision explicitly without causing migration churn for current DateTimeUTC users.
Issue #720 already mentions a future DateTimeUTC(fsp=…) extension as part of its broader ADK roadmap; this issue tracks the underlying type behavior independently.
Version
Observed with Advanced Alchemy 1.11.0 and confirmed against the current main implementation of advanced_alchemy/types/datetime.py.
Summary
DateTimeUTCcurrently wrapsDateTime(timezone=True). On MySQL it compiles toDATETIME(effectivelyDATETIME(0)), and on Oracle it compiles toDATE. Those types do not preserve fractional seconds.This matters for timestamps used in expiry or lease comparisons: a value such as
now + timedelta(milliseconds=50)is quantized to a whole second. Depending on the current fractional second, the stored deadline can expire too early or remain live hundreds of milliseconds too long.MCVE
Current output:
On MySQL, a test that stores a 50 ms expiry, waits 200 ms, and then evaluates
expires_at <= nowfails intermittently based on the acquisition time's fractional second. Compiling the column asDATETIME(6)makes the same test deterministic while retaining microseconds.Compatibility-safe direction
A non-breaking option would be to add an opt-in precision argument, for example
DateTimeUTC(fsp=6), while preserving today's DDL when the argument is omitted. The opt-in path could use:mysql.DATETIME(fsp=6)oracle.TIMESTAMPDateTimebehavior elsewhereA separate precise UTC timestamp type would also avoid changing existing schemas. Either approach would let applications request precision explicitly without causing migration churn for current
DateTimeUTCusers.Issue #720 already mentions a future
DateTimeUTC(fsp=…)extension as part of its broader ADK roadmap; this issue tracks the underlying type behavior independently.Version
Observed with Advanced Alchemy 1.11.0 and confirmed against the current
mainimplementation ofadvanced_alchemy/types/datetime.py.