Unix Timestamps in Python
Python provides several built-in ways to work with Unix timestamps. Whether you are logging events, storing dates in a database, or parsing API responses, understanding how Python handles epoch time will save you from subtle bugs. This guide covers every common operation with practical code you can copy into your project.
Getting the Current Unix Timestamp
The two most common approaches use the time and datetime modules.
Using time.time()
import time
ts = time.time()
print(ts) # 1711545600.123456
time.time() returns a float representing seconds since the Unix epoch (January 1, 1970 00:00:00 UTC). The fractional part gives you sub-second precision. If you only need an integer:
ts = int(time.time()) # 1711545600
Using datetime.now().timestamp()
from datetime import datetime
ts = datetime.now().timestamp()
print(ts) # 1711545600.123456
This returns the same float value. The difference is that datetime.now() creates a datetime object first, which is useful when you need both the timestamp and a formatted date.
Which should you use? Prefer time.time() when you only need the raw number. Use datetime.now().timestamp() when you are already working with datetime objects.
Converting a Timestamp to a Datetime
Local Time
from datetime import datetime
ts = 1711545600
dt = datetime.fromtimestamp(ts)
print(dt) # 2024-03-27 12:00:00 (depends on your local timezone)
fromtimestamp() converts the epoch value into a datetime object using your system's local timezone. This is fine for display purposes but can produce different results on different machines.
UTC Time
from datetime import datetime, timezone
ts = 1711545600
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
print(dt) # 2024-03-27 12:00:00+00:00
Always pass tz=timezone.utc when you need a consistent result regardless of where the code runs. The older datetime.utcfromtimestamp() method is deprecated since Python 3.12 because it returns a naive datetime that can be confused with local time.
Converting a Datetime to a Timestamp
from datetime import datetime, timezone
dt = datetime(2024, 3, 27, 12, 0, 0, tzinfo=timezone.utc)
ts = dt.timestamp()
print(ts) # 1711540800.0
If your datetime is timezone-aware, .timestamp() correctly computes the UTC epoch. If it is naive (no tzinfo), Python assumes local time, which can cause unexpected shifts.
Handling Timezones
Using zoneinfo (Python 3.9+)
The zoneinfo module is the modern, standard-library solution for timezone handling.
from datetime import datetime
from zoneinfo import ZoneInfo
# Create a timezone-aware datetime
dt_tokyo = datetime(2024, 3, 27, 21, 0, 0, tzinfo=ZoneInfo("Asia/Tokyo"))
dt_ny = dt_tokyo.astimezone(ZoneInfo("America/New_York"))
print(dt_tokyo) # 2024-03-27 21:00:00+09:00
print(dt_ny) # 2024-03-27 08:00:00-04:00
# Both produce the same timestamp
print(dt_tokyo.timestamp()) # 1711540800.0
print(dt_ny.timestamp()) # 1711540800.0
Using pytz (Legacy)
If you are on Python 3.8 or earlier, or maintaining existing code that uses pytz:
import pytz
from datetime import datetime
tz = pytz.timezone("US/Eastern")
dt = tz.localize(datetime(2024, 3, 27, 8, 0, 0))
print(dt.timestamp()) # 1711540800.0
Important: Never pass a pytz timezone directly to the datetime constructor. Always use tz.localize(). This is the most common pytz bug:
# WRONG - produces incorrect offset for many timezones
dt = datetime(2024, 3, 27, 8, 0, 0, tzinfo=pytz.timezone("US/Eastern"))
# CORRECT
dt = pytz.timezone("US/Eastern").localize(datetime(2024, 3, 27, 8, 0, 0))
Millisecond Timestamps
Some APIs (JavaScript, Java, many REST endpoints) use millisecond timestamps -- 13-digit numbers instead of 10.
import time
# Current time in milliseconds
ms = int(time.time() * 1000)
print(ms) # 1711545600123
# Convert milliseconds back to datetime
from datetime import datetime, timezone
ts_ms = 1711545600123
dt = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc)
print(dt) # 2024-03-27 12:00:00.123000+00:00
The rule is simple: divide by 1000 to go from milliseconds to seconds, multiply by 1000 to go the other way.
Formatting Timestamps as Strings
from datetime import datetime, timezone
dt = datetime.fromtimestamp(1711545600, tz=timezone.utc)
print(dt.isoformat()) # 2024-03-27T12:00:00+00:00
print(dt.strftime("%Y-%m-%d %H:%M:%S")) # 2024-03-27 12:00:00
print(dt.strftime("%B %d, %Y")) # March 27, 2024
Parsing Date Strings into Timestamps
from datetime import datetime, timezone
date_str = "2024-03-27T12:00:00Z"
dt = datetime.fromisoformat(date_str.replace("Z", "+00:00"))
print(dt.timestamp()) # 1711540800.0
In Python 3.11+, fromisoformat() handles the Z suffix directly. On older versions, replace Z with +00:00 as shown above.
Common Gotchas
| Gotcha | Fix |
|---|---|
utcfromtimestamp() returns naive datetime | Use fromtimestamp(ts, tz=timezone.utc) instead |
pytz timezone in constructor gives wrong offset | Use tz.localize() instead |
Naive datetime treated as local time by .timestamp() | Always attach a timezone before calling .timestamp() |
| Mixing seconds and milliseconds | Check digit count: 10 digits = seconds, 13 = milliseconds |
strftime on Windows does not support %-d | Use %#d on Windows or format manually |
Quick Reference
import time
from datetime import datetime, timezone
# Current timestamp (seconds)
time.time()
# Current timestamp (milliseconds)
int(time.time() * 1000)
# Timestamp to UTC datetime
datetime.fromtimestamp(ts, tz=timezone.utc)
# Datetime to timestamp
dt.timestamp()
# ISO format string
dt.isoformat()
Need to quickly verify a conversion? Try it online with DevToolBox -- paste any timestamp and see the result instantly without writing a single line of code.