Python datetime Module

Learn Python datetime module with examples for date, time, datetime, now(), strftime(), strptime(), ctime(), timestamps, timedelta, and time zones using zoneinfo.

Published

Updated

Read time 9 min read

Reviewed byDeepak Prasad

Python datetime Module

If you work with logs, APIs, or anything that says “when did this happen,” you spend a lot of time turning clocks into strings and back again. Below I start with the two-line version—read the current moment—then walk you through the datetime module the way you actually use it: building date, time, and datetime values, formatting with strftime, parsing with strptime, the fixed layout from ctime, Unix timestamps, timedelta math, and time zones with zoneinfo on modern Python.

I keep Google Calendar and other vendor APIs to a short troubleshooting section at the end; for Calendar-specific errors there is also a focused companion page you can jump to. The official datetime documentation remains the full reference.

Tested on: Python 3.13.3; kernel 6.14.0-37-generic.


Get current date and time

Run this first so you see what the module is for:

python
from datetime import datetime

now = datetime.now()
print(now)
Output

You should get something like 2026-06-20 15:42:31.123456 using your machine’s local clock (the exact numbers change every time, of course). That object is a datetime—a calendar date plus time-of-day—which is the type you will use most often.


What is datetime in Python?

The datetime module is part of the standard library. It gives you types for calendar dates (date), wall-clock times without a date (time), combined date-and-time (datetime), durations (timedelta), and time-zone hooks (tzinfo, plus timezone and, in examples below, ZoneInfo from zoneinfo).

For you the mental model is: you create values, turn them into strings for people or JSON, parse strings back into objects, shift instants with timedelta, and attach real zones when you cannot stay in “local time only.”


Import datetime in Python

You almost never need pip install for this—it ships with Python. Most code imports the types you use by name so call sites stay short:

python
from datetime import date, datetime, time, timedelta, timezone
from zoneinfo import ZoneInfo

print(date.today())
Output

You should see today’s date in ISO order YYYY-MM-DD. Adjust the import line to match what you need (for example skip ZoneInfo until you reach the time zone section).


Create date, time, and datetime objects

Build values explicitly when you are not reading “now” from the clock:

python
from datetime import date, datetime, time

d = date(2026, 6, 20)
t = time(14, 30, 0)
dt = datetime(2026, 6, 20, 14, 30, 0)
print(d, t, dt, sep="\n")
Output

You should see one line for the date, one for the time, and one full datetime. Notice month and day are not zero-padded in the constructor arguments, but printing uses the normal calendar rules.

You can also combine an existing date and time with datetime.combine(d, t) when you split those concerns in your code.


Format datetime using strftime()

When you need a string in a specific shape, use strftime with format codes. A compact cheat sheet lives at strftime.org; here is one pattern you will copy often:

python
from datetime import datetime

dt = datetime(2026, 6, 20, 14, 30, 5)
print(dt.strftime("%Y-%m-%d %H:%M:%S"))
print(dt.strftime("%d/%m/%Y %I:%M %p"))
Output

You should see 2026-06-20 14:30:05 on the first line and a locale-style 12-hour line on the second. If you are composing user-visible text, strftime is the tool you control end-to-end. For ideas that overlap with general string formatting, you may also like the string format guide.


Parse string to datetime using strptime()

strptime is the opposite of strftime: you give a pattern and Python fills a datetime for you.

python
from datetime import datetime

s = "2026-06-20 14:30:00"
dt = datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
print(dt, type(dt).__name__)
Output

You should get a datetime for 20 June 2026 at 14:30. If the string and pattern disagree, Python raises ValueError—that is your signal to fix the pattern or clean the input.


Use ctime() to format date and time

Sometimes you just want a readable English-style string without choosing codes. datetime.ctime() follows the C-style ctime layout (like time.ctime() for a Unix timestamp).

python
from datetime import datetime

dt = datetime(2026, 6, 20, 14, 30)
print(dt.ctime())
Output

On a typical Linux setup you should see something like Sat Jun 20 14:30:00 2026. The exact spacing can vary slightly with platform and locale, but the idea is fixed: weekday, month, day, time, year.

When you need a custom layout or localized month names, switch to strftime; use ctime when “good enough, right now” is enough.


Convert timestamp to datetime

Unix timestamps count seconds from the epoch (UTC). fromtimestamp builds a local datetime by default; pass tz=timezone.utc when you want UTC explicitly. See also Python to timestamp for pandas Period.to_timestamp() patterns.

python
from datetime import datetime, timezone

timestamp = 1718872200
local_dt = datetime.fromtimestamp(timestamp)
utc_dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
print(local_dt)
print(utc_dt)
Output

The first line follows your machine’s local zone; the second should show an aware UTC value with +00:00. Pick the one that matches how you stored the timestamp.


Convert datetime to timestamp

timestamp() returns seconds since the epoch as a float. For naive datetimes, Python uses the local time interpretation documented for your platform—when you care about portability, build an aware datetime with timezone or ZoneInfo first.

python
from datetime import datetime, timezone

naive = datetime(2026, 6, 20, 14, 30)
aware_utc = datetime(2026, 6, 20, 14, 30, tzinfo=timezone.utc)
print(naive.timestamp())
print(aware_utc.timestamp())
Output

Both calls should print numeric floats; the exact values can differ between the naive and UTC-aware case depending on your local offset.


Add or subtract dates using timedelta

timedelta represents a duration. You add or subtract it from date or datetime objects to move forward or backward on the timeline.

python
from datetime import datetime, timedelta

dt = datetime(2026, 6, 20, 12, 0)
later = dt + timedelta(days=3, hours=4)
earlier = dt - timedelta(weeks=1)
print(later)
print(earlier)
Output

You should see dt shifted forward by three days and four hours, and backward by one week.


Difference between two dates or datetimes

Subtract two datetime values (or two date values) and you get a timedelta describing the gap.

python
from datetime import date, datetime

d1 = date(2026, 6, 1)
d2 = date(2026, 6, 20)
print(d2 - d1)

a = datetime(2026, 6, 20, 18, 0)
b = datetime(2026, 6, 19, 10, 0)
print(a - b)
Output

You should see 19 days, 0:00:00 for the dates and 1 day, 8:00:00 for the datetimes. Call .total_seconds() on the result when you need a single number for storage or metrics.


Work with time zones using zoneinfo

On Python 3.9+, zoneinfo reads the IANA time zone database (your OS data or the tzdata package on Windows). That is what I reach for first in new code.

python
from datetime import datetime
from zoneinfo import ZoneInfo

dt_kolkata = datetime.now(ZoneInfo("Asia/Kolkata"))
dt_ny = datetime.now(ZoneInfo("America/New_York"))
print(dt_kolkata)
print(dt_ny)
Output

You should see two “now” values with different offsets. Build aware datetimes when you cross zones or serialize to APIs; stay naive only when you are sure everything happens in one implicit zone.

Legacy note: The third-party pytz library predates zoneinfo and appears in older tutorials. If you maintain legacy code that already imports pytz, keep it consistent there; for new projects on supported Python versions, prefer zoneinfo and IANA names like Europe/London instead of reinventing offsets by hand.


Fix unknown time zone errors

APIs such as Google Calendar expect RFC3339 date-time strings (include an offset like +05:30 or Z) and, when you set the timeZone field, a valid IANA time zone name such as Asia/Kolkata or America/New_York. Short abbreviations like IST, PST, or EST are ambiguous across regions and often trigger “unknown time zone” style failures because they are not stable identifiers in the IANA database.

python
event = {
    "summary": "Team meeting",
    "start": {
        "dateTime": "2026-06-20T14:00:00+05:30",
        "timeZone": "Asia/Kolkata",
    },
    "end": {
        "dateTime": "2026-06-20T15:00:00+05:30",
        "timeZone": "Asia/Kolkata",
    },
}

print(event["start"]["timeZone"])
Output

You should see Asia/Kolkata printed. Pair that habit—IANA name plus explicit offset in dateTime—with the API’s own wording about required formats.

If Calendar errors are your main problem, read the focused walkthrough Fix unknown time zone error in Google Calendar API next.


datetime vs date vs time vs timedelta

  • date is just year-month-day—use it for birthdays, deadlines without a clock, or all-day calendar days.
  • time is clock time without a calendar anchor—rare alone, common when you combine with date.
  • datetime is the workhorse: calendar day plus clock, with optional tzinfo.
  • timedelta is a duration you add, subtract, or compare after subtracting two dates or datetimes.

When you are unsure, default to datetime for instants and timedelta for “how long” or “how far apart.”


Common mistakes with Python datetime

Things I still watch for in reviews:

  • Mixing naive and aware values in arithmetic—pick one model per pipeline and convert explicitly with replace(tzinfo=...) or astimezone.
  • Calling datetime the module and datetime the class—use from datetime import datetime or import datetime as dt to avoid the name clash tripping you up.
  • Parsing locale-specific strings with the wrong strptime pattern—match the string exactly, including zero padding and AM/PM markers.
  • Assuming strftime("%Z") always gives a stable zone name—it can be empty or abbreviated; use ZoneInfo identifiers when you need something API-safe.
  • Using datetime.utcnow() and then treating the value as “timezone safe”—it is naive UTC; prefer datetime.now(timezone.utc) for an aware UTC clock reading.
  • Forgetting that date.today() and datetime.now() follow the machine’s local zone unless you pass a tz.

Python datetime quick reference table

What you want Typical code
Today’s date date.today()
Right now (local) datetime.now()
Right now in a zone datetime.now(ZoneInfo("Asia/Kolkata"))
Format to string dt.strftime("%Y-%m-%d %H:%M:%S")
Parse from string datetime.strptime(text, pattern)
Quick fixed layout dt.ctime()
Unix seconds → datetime datetime.fromtimestamp(ts, tz=timezone.utc)
datetime → Unix seconds dt.timestamp()
Add a duration dt + timedelta(days=1, hours=2)
Gap between instants dt2 - dt1 (gives timedelta)

Summary

You have seen how the datetime module lets you capture instants (datetime.now()), build values (date, time, datetime), format and parse strings (strftime, strptime), grab a quick display string (ctime), move between Unix timestamps and objects (fromtimestamp, timestamp), slide along the timeline with timedelta, and pin events to real zones with zoneinfo and IANA names. When you talk to calendar APIs, pair RFC3339 offsets with those IANA names instead of short abbreviations, and use the companion article linked above when Calendar itself is the headache.


References


Frequently Asked Questions

1. What is the difference between naive and aware datetime objects?

A naive datetime has no time zone attached—Python treats arithmetic and timestamps relative to local rules where documented; an aware datetime carries a tzinfo (for example from zoneinfo) so offsets and DST are explicit.

2. Should I use pytz or zoneinfo for time zones in new code?

Prefer zoneinfo from the standard library on Python 3.9+ with IANA names like Asia/Kolkata; keep pytz only when you must support older stacks or legacy code already built on it.

3. Why does Google Calendar API reject my time zone string?

The API expects IANA names such as America/New_York or Asia/Kolkata in the timeZone field and RFC3339 date-time strings with offsets for dateTime; abbreviations like IST or PST are ambiguous and should be avoided.

4. When should I use strftime instead of ctime?

Use ctime() for a quick fixed English-style string from a datetime; use strftime when you need a specific layout, locale-friendly formatting, or parts of the value in a custom order.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …