ToolNest logoToolNest.

How to Convert Unix Timestamp to Date in Python

How to convert unix timestamp to date in python? Use datetime.fromtimestamp(ts, tz=timezone.utc) — e.g. fromtimestamp(1760745600, tz=timezone.utc) returns 2025-10-18 00:00:00+00:00. For millisecond timestamps, divide by 1,000 first. Never use utcfromtimestamp (deprecated since Python 3.12). Verify epoch values with our free unix timestamp converter.

The One-Liner: datetime.fromtimestamp

To python convert epoch to datetime, one line does it: from datetime import datetime, timezone then datetime.fromtimestamp(1760745600, tz=timezone.utc) → 2025-10-18 00:00:00+00:00. The timestamp is seconds since the Unix epoch (1970-01-01 00:00:00 UTC); fromtimestamp walks that many seconds forward from the epoch and hands you a datetime. The tz=timezone.utc argument is doing critical work: without it you get a naive datetime in your machine's local timezone — the same timestamp returns different hours on a laptop in New York versus one in Tokyo, which is the #1 source of timestamp bugs. Always pass an explicit timezone; timezone.utc is the sane default, and you can convert to any local zone afterward with .astimezone(). For quick one-off checks without writing code, paste the value into our unix timestamp converter — it handles 10- and 13-digit values and shows UTC plus your local time side by side.

Milliseconds, Microseconds, and Nanoseconds

APIs disagree on timestamp precision, and feeding the wrong unit to fromtimestamp produces absurd dates — a millisecond timestamp read as seconds lands in the year 52687. The rule: divide down to seconds first. Milliseconds (13 digits, e.g. JavaScript's Date.now()): datetime.fromtimestamp(1760745600000 / 1000, tz=timezone.utc). Microseconds (16 digits, e.g. some databases): divide by 1_000_000. Nanoseconds (19 digits, e.g. time.time_ns()): divide by 1_000_000_000. How to tell which you have: count the digits — 10 digits is seconds (covers 2001–2286), 13 is milliseconds, 16 is microseconds, 19 is nanoseconds. A defensive pattern that auto-detects: ts = ts / 1000 if ts > 1e12 else ts — any value above a trillion must be milliseconds or finer, since seconds will not reach a trillion until the year 33658. One subtlety: dividing introduces floats, and floats lose sub-microsecond precision — for nanosecond-exact work, do integer math (seconds, nanos = divmod(ts_ns, 1_000_000_000)) and pass tzinfo explicitly. Our unix timestamp in Excel guide covers the same unit-sniffing for spreadsheet timestamps.

Timezones Done Right: Aware vs Naive

Python datetime fromtimestamp has a split personality: with tz you get an aware datetime (it knows its timezone, shown by the +00:00 suffix); without it you get a naive one (no timezone info, silently local time). Aware datetimes are the only ones you should compute with — subtracting two naive datetimes from different zones gives nonsense, while aware datetimes convert correctly. The modern pattern: from datetime import datetime, timezone / dt = datetime.fromtimestamp(ts, tz=timezone.utc) / local = dt.astimezone(ZoneInfo('America/New_York')) (import ZoneInfo from zoneinfo, stdlib since 3.9). This handles daylight saving correctly — the same UTC instant renders as EDT or EST depending on the date, which manual offset math gets wrong twice a year. Never do arithmetic on naive datetimes across a DST boundary, and never store naive datetimes in a database if the readers might be in another timezone. The mantra: parse in UTC, store in UTC, display in local — convert to the user's zone only at the last moment, at the edge of your program.

Formatting the Result

A datetime object is for computing; humans want strings. dt.strftime('%Y-%m-%d %H:%M:%S') gives 2025-10-18 00:00:00; dt.isoformat() gives 2025-10-18T00:00:00+00:00, the ISO 8601 form APIs expect. Common format codes: %Y year, %m month, %d day, %H hour (24h), %M minute, %S second, %A weekday name, %B month name, %z UTC offset. For filenames, dt.strftime('%Y%m%d-%H%M%S') sorts chronologically as plain text. For JSON APIs, dt.isoformat() is the lingua franca — or go back to a timestamp with dt.timestamp(), which returns the float seconds-since-epoch (the exact reverse of fromtimestamp, and it respects the datetime's timezone, so aware datetimes round-trip perfectly). One trap: str(dt) on a naive datetime looks identical to UTC output — 2025-10-18 00:00:00 with no suffix — which is how local-time values get misread as UTC in logs. When in doubt, .isoformat() never hides the timezone.

Going the Other Way: Date to Timestamp

The reverse trip answers how to get current unix timestamp in python and converts any datetime back to epoch seconds. Right now: import time; time.time() → 17607... (float seconds, the fastest call). Or timezone-aware: from datetime import datetime, timezone; datetime.now(timezone.utc).timestamp(). From an existing datetime: dt.timestamp() — aware datetimes convert exactly; naive datetimes are assumed to be local time, which is correct only if they actually are. From date parts: datetime(2025, 10, 18, tzinfo=timezone.utc).timestamp() → 1760745600.0. From a string: datetime.fromisoformat('2025-10-18T00:00:00+00:00').timestamp(). Note the asymmetry: timestamp() on a naive datetime uses your system timezone, so the same code returns different epochs on different machines — the mirror image of the fromtimestamp trap in section one. For elapsed-time measurement (benchmarks, timeouts), skip wall-clock entirely: time.monotonic() never jumps when the system clock is adjusted, while time.time() can leap forward or backward under NTP corrections.

utcfromtimestamp Is Deprecated: Stop Using It

You will still find datetime.utcfromtimestamp(ts) in old tutorials and Stack Overflow answers — it has been deprecated since Python 3.12 and emits a DeprecationWarning. It returns a naive datetime that looks like UTC but carries no timezone, which is precisely the ambiguity the language is trying to kill. The migration is mechanical: replace datetime.utcfromtimestamp(ts) with datetime.fromtimestamp(ts, tz=timezone.utc) everywhere. Same for its sibling datetime.utcnow() → datetime.now(timezone.utc). If you maintain a library, the deprecation means your users on 3.12+ see warnings they cannot silence without upgrading you — grep your codebase for utcfromtimestamp and utcnow today. The broader lesson: Python's datetime modernization is converging on aware-by-default, and every new timestamp API (datetime.fromtimestamp(ts, tz=...), ZoneInfo, datetime.now(timezone.utc)) pushes the same direction. Write new code the aware way and the deprecations will never touch you.

Common Pitfalls

Five ways timestamps bite. 13-digit timestamps read as seconds: fromtimestamp(1760745600000) → year 52687 — divide by 1,000 first (section two). Local-time surprises: fromtimestamp(ts) without tz uses the server's timezone — code tested in Chicago breaks in a UTC Docker container; always pass tz explicitly. Naive-datetime arithmetic: subtracting datetimes from different zones without tzinfo silently computes garbage; make both aware first. Pre-1970 timestamps on Windows: negative epochs (dates before 1970) can raise OSError on Windows via fromtimestamp — add timedelta to the epoch manually (datetime(1970,1,1,tzinfo=timezone.utc) + timedelta(seconds=ts)) for a portable path. The Year 2038 problem: 32-bit systems overflow signed 32-bit time at 03:14:07 UTC on 2038-01-19 — Python ints are unbounded so your code is fine, but timestamps stored in 32-bit database columns or C structs are not; prefer 64-bit columns for anything with a long life. When a timestamp looks wrong, paste it into the unix timestamp converter first — seeing the UTC and local renderings side by side diagnoses unit and timezone errors in seconds.

Quick Answers

How to convert unix timestamp to date in python? datetime.fromtimestamp(ts, tz=timezone.utc) — one line, timezone-safe. How do I convert milliseconds? Divide by 1,000 first: fromtimestamp(ms/1000, tz=timezone.utc). What replaced utcfromtimestamp? fromtimestamp(ts, tz=timezone.utc) — the old function is deprecated since Python 3.12. How do I get the current timestamp? time.time() for a float, or datetime.now(timezone.utc).timestamp() for the aware-datetime route. Why does my datetime show the wrong hour? Almost certainly a naive datetime rendered in local time — pass tz=timezone.utc and convert with .astimezone() only for display. For JWT expiry timestamps and other epoch-adjacent formats, our JWT decoder guide shows where these timestamps hide in tokens — and the ToolNest homepage has the full free developer toolbox.

Do it in one click

Convert Unix timestamps instantly — free, no signup.

Open the Free Tool →