Skip to content
FreeAIDevTools

Epoch Converter in Python

Convert Unix timestamps to dates and back in Python: the idiomatic code, the gotchas, and a live converter.

How do you convert a Unix timestamp to a datetime in Python? Call datetime.fromtimestamp(ts, tz=timezone.utc) to get an aware UTC datetime, and dt.timestamp() to go back to epoch seconds. Python expects seconds, so divide a 13-digit millisecond value by 1000 first or fromtimestamp raises ValueError because the year lands around 58281.

Epoch to date (Python)
from datetime import datetime, timezone

ts = 1777010400
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
print(dt)  # 2026-04-24 06:00:00+00:00
Date to epoch (Python)
from datetime import datetime, timezone

dt = datetime(2026, 4, 24, 6, 0, 0, tzinfo=timezone.utc)
ts = int(dt.timestamp())
print(ts)  # 1777010400
Now: …
Open the full Epoch Converter →

The Inference Report · Every Tuesday

Know when AI prices change.

One short email every Tuesday: new models, price moves and free tiers that were cut or added. Five minutes, no fluff.

No spam. Unsubscribe anytime.

Naive datetimes are the Python trap

Python happily builds datetime objects with no timezone attached, and those naive objects are where almost every off-by-hours bug starts. A naive datetime is interpreted as local time the moment you call .timestamp() on it, so the same code produces different epochs on a laptop in Karachi and a server in us-east-1. Always pass tz=timezone.utc to fromtimestamp and always attach tzinfo when constructing datetimes by hand.

The older shortcuts made this worse. datetime.utcnow() and datetime.utcfromtimestamp() return naive objects that look like UTC but carry no zone, and both are deprecated as of Python 3.12. The modern replacements are datetime.now(timezone.utc) and datetime.fromtimestamp(ts, tz=timezone.utc). If you see utcfromtimestamp in a codebase, treat it as a bug waiting to be scheduled.

Seconds in, seconds out

Python's epoch convention is seconds as a float, matching time.time(). That clashes with anything that crossed a JavaScript boundary, because browser code emits 13-digit milliseconds. If fromtimestamp raises ValueError with a year around 58281, you fed it milliseconds; divide by 1000 first. Going the other way, dt.timestamp() returns a float with sub-second precision, so wrap it in int() before putting it in a JWT exp claim or any API that validates whole seconds.

Frequently asked

Why is my Python datetime off by several hours?

You almost certainly converted through a naive datetime, which Python interprets in the machine's local timezone. Pass tz=timezone.utc to fromtimestamp and attach tzinfo when building datetimes so the conversion is anchored to UTC instead of wherever the code happens to run.

Is datetime.utcfromtimestamp deprecated?

Yes, since Python 3.12, along with utcnow(). Both return naive datetimes that silently lose the UTC context. Use datetime.fromtimestamp(ts, tz=timezone.utc) and datetime.now(timezone.utc) instead; they return aware objects that survive further arithmetic and formatting correctly.

How do I get milliseconds since epoch in Python?

Use int(time.time() * 1000), or for an existing aware datetime, int(dt.timestamp() * 1000). Python has no built-in millisecond epoch function because its native convention is float seconds, so the multiplication is idiomatic and expected.

More in this series