X Xerobit

Unix Timestamps in Python — datetime, time, and Arrow

Work with Unix timestamps in Python using the datetime module, time.time(), and the arrow library. Covers converting timestamps to datetime objects, timezone-aware timestamps,...

Mian Ali Khalid · · 5 min read
Use the tool
Timestamp Converter
Convert Unix timestamps, epoch seconds/milliseconds, and ISO 8601 dates.
Open Timestamp Converter →

Python’s datetime module handles Unix timestamps reliably when you’re careful about timezone awareness. The arrow library simplifies timezone-aware datetime operations.

Convert timestamps instantly with the Timestamp Converter.

Get current Unix timestamp

import time
from datetime import datetime, timezone

# Seconds since Unix epoch (1970-01-01T00:00:00Z)
now_float = time.time()          # 1747066800.123456 (float)
now_int = int(time.time())       # 1747066800 (integer)

# Milliseconds (for JavaScript compatibility):
now_ms = int(time.time() * 1000) # 1747066800123

# Using datetime (recommended — timezone explicit):
now_utc = datetime.now(timezone.utc)
timestamp = now_utc.timestamp()  # 1747066800.123456

Convert timestamp to datetime

from datetime import datetime, timezone

timestamp = 1747066800

# ✅ Timezone-aware (correct):
dt_utc = datetime.fromtimestamp(timestamp, tz=timezone.utc)
# datetime(2026, 5, 12, 14, 0, 0, tzinfo=timezone.utc)

# ❌ Avoid: returns LOCAL timezone datetime (varies by machine):
dt_local = datetime.fromtimestamp(timestamp)

# ✅ Alternative using utcfromtimestamp (but still naive!):
dt_naive = datetime.utcfromtimestamp(timestamp)
# Use this only if you're certain you want a naive datetime

# Format the result:
dt_utc.strftime('%Y-%m-%d %H:%M:%S UTC')  # "2026-05-12 14:00:00 UTC"
dt_utc.isoformat()                         # "2026-05-12T14:00:00+00:00"

Convert datetime to timestamp

from datetime import datetime, timezone

# Timezone-aware datetime → timestamp:
dt = datetime(2026, 5, 12, 14, 0, 0, tzinfo=timezone.utc)
ts = dt.timestamp()        # 1747066800.0

# ISO string → timestamp:
iso_str = '2026-05-12T14:00:00Z'
dt = datetime.fromisoformat(iso_str.replace('Z', '+00:00'))
ts = dt.timestamp()

# Python 3.11+ can parse 'Z' directly:
dt = datetime.fromisoformat('2026-05-12T14:00:00Z')  # Python 3.11+

Timezone handling with zoneinfo (Python 3.9+)

from datetime import datetime
from zoneinfo import ZoneInfo  # Python 3.9+

utc = ZoneInfo('UTC')
ny = ZoneInfo('America/New_York')
ist = ZoneInfo('Asia/Kolkata')

# Create timezone-aware datetime:
dt_utc = datetime(2026, 5, 12, 14, 0, 0, tzinfo=utc)

# Convert to another timezone:
dt_ny = dt_utc.astimezone(ny)   # 2026-05-12 10:00:00-04:00
dt_ist = dt_utc.astimezone(ist) # 2026-05-12 19:30:00+05:30

# Get Unix timestamp (same regardless of timezone):
dt_utc.timestamp() == dt_ny.timestamp()  # True

# For Python < 3.9, use pytz:
# pip install pytz
import pytz
ny = pytz.timezone('America/New_York')
dt_ny = dt_utc.astimezone(ny)

Arrow library (simpler API)

pip install arrow
import arrow

# Current time:
now = arrow.utcnow()
now.timestamp()           # 1747066800.123456
now.isoformat()           # "2026-05-12T14:00:00.123456+00:00"

# From timestamp:
dt = arrow.Arrow.fromtimestamp(1747066800)
dt.isoformat()            # "2026-05-12T14:00:00+00:00"

# Timezone conversion:
ny = dt.to('America/New_York')
ist = dt.to('Asia/Kolkata')

# Relative time:
dt.humanize()             # "just now", "2 hours ago", "in 3 days"

# Shift (add/subtract):
tomorrow = arrow.utcnow().shift(days=1)
last_week = arrow.utcnow().shift(weeks=-1)

# Format:
dt.format('YYYY-MM-DD HH:mm:ss')  # "2026-05-12 14:00:00"
dt.format('ddd, MMM D YYYY')      # "Tue, May 12 2026"

Common timestamp patterns

from datetime import datetime, timezone, timedelta

def is_expired(timestamp: int, ttl_seconds: int = 3600) -> bool:
    """Check if a timestamp is older than ttl_seconds."""
    return (datetime.now(timezone.utc).timestamp() - timestamp) > ttl_seconds

def timestamp_to_iso(ts: int | float) -> str:
    """Convert Unix timestamp to ISO 8601 string."""
    return datetime.fromtimestamp(ts, tz=timezone.utc).isoformat()

def iso_to_timestamp(iso: str) -> int:
    """Convert ISO 8601 string to Unix timestamp (integer)."""
    dt = datetime.fromisoformat(iso.replace('Z', '+00:00'))
    return int(dt.timestamp())

def start_of_day_utc(ts: int) -> int:
    """Get the Unix timestamp for midnight UTC of the given timestamp's day."""
    dt = datetime.fromtimestamp(ts, tz=timezone.utc)
    midnight = dt.replace(hour=0, minute=0, second=0, microsecond=0)
    return int(midnight.timestamp())

# Usage:
print(timestamp_to_iso(1747066800))     # "2026-05-12T14:00:00+00:00"
print(iso_to_timestamp('2026-05-12T14:00:00Z'))  # 1747066800
print(is_expired(1747066800 - 7200))    # True (2 hours ago, TTL=1 hour)

Formatting for API responses

from datetime import datetime, timezone
from typing import Optional

def format_api_datetime(
    dt: Optional[datetime] = None,
    ts: Optional[int | float] = None,
    fmt: str = 'iso',
) -> str:
    """
    Format a datetime for API responses.
    fmt options: 'iso', 'unix', 'human'
    """
    if ts is not None:
        dt = datetime.fromtimestamp(ts, tz=timezone.utc)
    elif dt is None:
        dt = datetime.now(timezone.utc)
    
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
    
    if fmt == 'iso':
        return dt.isoformat()              # "2026-05-12T14:00:00+00:00"
    elif fmt == 'unix':
        return str(int(dt.timestamp()))    # "1747066800"
    elif fmt == 'human':
        return dt.strftime('%B %d, %Y')    # "May 12, 2026"
    raise ValueError(f"Unknown format: {fmt}")

Related posts

Related tool

Timestamp Converter

Convert Unix timestamps, epoch seconds/milliseconds, and ISO 8601 dates.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.