date.today / datetime.now / utcnow

Three ways to ask "what time is it?" — only one of them gives an unambiguous answer: datetime.now(UTC). utcnow() returns the same numbers without a tzinfo and has been deprecated since Python 3.12.

datetime class methodPython 2.3+ (utcnow deprecated 3.12)Live demo
Common call
datetime.now(UTC)
Returns
an aware datetime, tzinfo=datetime.timezone.utc
Replaces
datetime.utcnow() and time.time() for timestamps you keep
Watch out
now() without tz is naive LOCAL time — machine-dependent
datetime.now(tztz — None: naive local wall time of the machine. A tzinfo (UTC, timezone(...), ZoneInfo): an aware datetime in that zone.type: tzinfo | None · default: None=None)
→ datetime

Demo

Live evaluation
The clock reading itself changes every run, so the demo shows only what now(tz) guarantees: the offset and name of the zone you passed.
Try:
Inputs
hoursintoffset in hours
Code
from datetime import datetime, timedelta, timezone
now = datetime.now(timezone(timedelta(hours=0)))
(now.utcoffset(), now.tzname())
Result
(datetime.timedelta(0), 'UTC')

Whatever the moment, now(tz) is aware and reports the zone it was given; timezone(timedelta(0)) is timezone.utc, named "UTC". The actual time value is left out on purpose: it changes every call and depends on the machine clock.

Parameters

NameTypeRequiredDescription
tztzinfo | Noneno (None)None: naive local wall time of the machine. A tzinfo (UTC, timezone(...), ZoneInfo): an aware datetime in that zone.

Return value

datetime — now(): naive local time without tz, aware time in tz with it. date.today(): the local date. utcnow(): naive UTC fields.

Common patterns

Timestamp for storage
Aware, UTC, ISO text.
from datetime import datetime, UTC
created_at = datetime.now(UTC).isoformat()
Local time for display
astimezone() with no argument converts to the machine's local zone.
from datetime import datetime, UTC
local = datetime.now(UTC).astimezone()
Today in a specific zone
date.today() uses the machine zone; ask now(tz) and take .date() instead.
from datetime import datetime
from zoneinfo import ZoneInfo
today_in_tokyo = datetime.now(ZoneInfo('Asia/Tokyo')).date()
Replacing utcnow()
Same instant, but aware. Code comparing with naive values must be updated too.
from datetime import datetime, UTC
# before: datetime.utcnow()
now = datetime.now(UTC)

Examples

1. now(UTC) is aware
from datetime import datetime, UTC datetime.now(UTC).tzinfo
Returns
datetime.timezone.utc
2. now() is naive
from datetime import datetime datetime.now().tzinfo is None
Returns
True
3. today() returns a date
from datetime import date type(date.today()).__name__
Returns
'date'
4. utcnow() is deprecated (3.12+)
import warnings from datetime import datetime with warnings.catch_warnings(record=True) as caught: warnings.simplefilter("always") datetime.utcnow() (caught[0].category.__name__, str(caught[0].message).split(" and ")[0])
Returns
('DeprecationWarning', 'datetime.datetime.utcnow() is deprecated')
5. tz must be a tzinfo
from datetime import datetime datetime.now(5)
Returns
TypeError: tzinfo argument must be None or of a tzinfo subclass, not type 'int'
6. date.today() takes no zone
from datetime import date, UTC date.today(UTC)
Returns
TypeError: date.today() takes no arguments (1 given)

Pitfalls

1. utcnow() gives a naive value
The fields are UTC but tzinfo is None, so it compares wrongly (or not at all) against aware values — the reason it was deprecated in 3.12.
utcnow()
import warnings
from datetime import datetime
with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    now = datetime.utcnow()
now.tzinfo is None
True
now(UTC)
from datetime import datetime, UTC
datetime.now(UTC).tzinfo is UTC
True
2. Comparing now() with an aware value
now() without tz is naive, so it cannot be ordered against parsed ISO timestamps that carry an offset.
naive now()
from datetime import datetime
datetime.now() < datetime.fromisoformat('2999-01-01T00:00Z')
TypeError: can't compare offset-naive and offset-aware datetimes
now(UTC)
from datetime import datetime, UTC
datetime.now(UTC) < datetime.fromisoformat('2999-01-01T00:00Z')
True

When to use

Use it
  • datetime.now(UTC) for anything stored or compared
  • date.today() for a local calendar date on a single machine (scripts, reports)
Reach for something else
  • utcnow() → now(UTC)
  • Measuring durations → time.perf_counter() (now() can jump when the clock is adjusted)
  • Server code that must know the user's date → now(user_zone).date(), not date.today()

Notes

CPython impl
now() reads the system clock at microsecond resolution and converts it with localtime(), or for a tz with gmtime() followed by tz.fromutc()
Deprecation
utcnow() emits DeprecationWarning since 3.12: "datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC)."
today()
datetime.today() is the same as datetime.now() without tz; date.today() takes no arguments

FAQ

It returns a naive datetime whose fields are UTC. Python treats naive values as local time in methods like timestamp() and astimezone(), so utcnow() results were silently misinterpreted. Since 3.12 it emits a DeprecationWarning; use datetime.now(UTC) (or now(timezone.utc) before 3.11).