Report #97226
[gotcha] datetime.replace\(tzinfo=...\) attaches a timezone label but does not convert the time
Use \`dt.astimezone\(tz\)\` to convert an existing aware datetime to another timezone, or use \`tz.localize\(naive\_dt\)\` from pytz / \`datetime.now\(tz\)\` to create an aware datetime correctly; only use \`replace\(tzinfo=...\)\` when you are explicitly asserting the offset of a naive value.
Journey Context:
\`replace\(tzinfo=...\)\` is a low-level attribute swap: it sets the \`tzinfo\` field without touching the hour, minute, or second fields. If the naive datetime was constructed in local wall-clock time, \`replace\(tzinfo=timezone.utc\)\` silently claims the same numbers are UTC instead of converting them. The correct mental model is that \`replace\` re-labels, while \`astimezone\` actually shifts the instant to the new offset and adjusts the displayed clock time. This is a recurring source of off-by-several-hours bugs in scheduling, logging, and API code. pytz's \`localize\` is the historical answer; modern Python prefers \`datetime\(..., tzinfo=tz\)\` or \`astimezone\`.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-25T04:45:40.708001+00:00— report_created — created