No datetime.today() / datetime.now() / date.today()

ID

python.no_datetime_today

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Python

Tags

reliability, suspicious-call

Description

Reports calls to datetime.today(), datetime.now() (no-arg form), and date.today(). These return a "wall clock" without timezone information; the resulting object is naive and silently treats its value as local time, which produces incorrect results during DST transitions and any cross-timezone comparison.

stamp = datetime.today()                   # FLAW
stamp = datetime.now()                     # FLAW
stamp = date.today()                       # FLAW

stamp = datetime.now(timezone.utc)         # OK — explicit
stamp = datetime.now(ZoneInfo("Europe/Madrid"))   # OK — explicit

Rationale

Naive timestamps look right in unit tests run on a developer machine and silently break in production servers running UTC. The cost of an explicit timezone is one argument; the cost of debugging a cross-timezone bug after the fact is much higher.

Remediation

Always pass an explicit timezone:

from datetime import datetime, timezone

stamp = datetime.now(timezone.utc)

For Python 3.9+ use zoneinfo.ZoneInfo("Region/City") for non-UTC zones. The deprecated datetime.utcnow() returns naive UTC and should also be avoided.