Python
datetime
UTC
timestamp
conversion

Converting datetime.date to UTC timestamp in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

A datetime.date object represents a calendar date without a time or timezone. Converting it to a UTC timestamp (seconds since 1970-01-01 00:00:00 UTC) requires deciding what time of day and what timezone the date represents. The standard approach is to treat the date as midnight UTC, combine it with time(0, 0) and timezone.utc, then call .timestamp(). Getting this wrong is the most common source of timestamp bugs in Python.

The Direct Approach (Python 3.3+)

python
1from datetime import date, datetime, timezone
2
3d = date(2025, 9, 24)
4
5# Combine with midnight UTC, then get timestamp
6dt = datetime.combine(d, datetime.min.time(), tzinfo=timezone.utc)
7timestamp = dt.timestamp()
8print(timestamp)  # 1758672000.0
9
10# Verify round-trip
11print(datetime.fromtimestamp(timestamp, tz=timezone.utc).date())
12# 2025-09-24

Why date Alone Is Ambiguous

python
1from datetime import date, datetime, timezone
2
3d = date(2025, 6, 15)
4
5# Without timezone: assumes LOCAL timezone
6naive = datetime.combine(d, datetime.min.time())
7ts_local = naive.timestamp()
8
9# With UTC timezone: midnight UTC
10aware = datetime.combine(d, datetime.min.time(), tzinfo=timezone.utc)
11ts_utc = aware.timestamp()
12
13print(f"Local timestamp: {ts_local}")  # Depends on your system timezone
14print(f"UTC timestamp:   {ts_utc}")    # Always the same everywhere
15
16# The difference equals your UTC offset in seconds
17print(f"Difference: {ts_local - ts_utc} seconds")
18# e.g., -18000.0 for US Eastern (UTC-5)

datetime.timestamp() on a naive datetime assumes local time. This means the same code produces different timestamps on different machines.

Using calendar.timegm()

python
1import calendar
2from datetime import date
3
4d = date(2025, 9, 24)
5
6# timegm() treats the input as UTC (unlike mktime which uses local time)
7timestamp = calendar.timegm(d.timetuple())
8print(timestamp)  # 1758672000

calendar.timegm() is the UTC equivalent of time.mktime(). It always interprets the input as UTC regardless of the system timezone.

Using time.mktime() (Local Time, Usually Wrong)

python
1import time
2from datetime import date
3
4d = date(2025, 9, 24)
5
6# mktime() interprets the input in the LOCAL timezone
7timestamp = time.mktime(d.timetuple())
8print(timestamp)  # Result depends on system timezone

time.mktime() converts local time to a timestamp. If you want UTC, do not use this. Use calendar.timegm() instead.

Integer vs Float Timestamps

python
1from datetime import date, datetime, timezone
2
3d = date(2025, 9, 24)
4dt = datetime.combine(d, datetime.min.time(), tzinfo=timezone.utc)
5
6# Float timestamp (includes microseconds)
7ts_float = dt.timestamp()
8print(ts_float)      # 1758672000.0
9print(type(ts_float)) # <class 'float'>
10
11# Integer timestamp
12ts_int = int(dt.timestamp())
13print(ts_int)        # 1758672000
14
15# For millisecond timestamps (JavaScript-style)
16ts_ms = int(dt.timestamp() * 1000)
17print(ts_ms)         # 1758672000000

Converting Back (Timestamp to date)

python
1from datetime import datetime, timezone
2
3timestamp = 1758672000
4
5# Always specify UTC when converting back
6dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
7d = dt.date()
8print(d)  # 2025-09-24
9
10# Without tz, fromtimestamp uses LOCAL timezone
11# This may give a different date near midnight!
12dt_local = datetime.fromtimestamp(timestamp)
13print(dt_local.date())  # Could be 2025-09-23 in western timezones

With Timezone-Aware Dates

python
1from datetime import date, datetime, time
2from zoneinfo import ZoneInfo  # Python 3.9+
3
4d = date(2025, 9, 24)
5
6# Midnight in New York
7ny_midnight = datetime.combine(d, time(0, 0), tzinfo=ZoneInfo("America/New_York"))
8print(ny_midnight.timestamp())  # 1758686400.0 (4 hours after UTC midnight)
9
10# Midnight in Tokyo
11tokyo_midnight = datetime.combine(d, time(0, 0), tzinfo=ZoneInfo("Asia/Tokyo"))
12print(tokyo_midnight.timestamp())  # 1758639600.0 (9 hours before UTC midnight)
13
14# Midnight in UTC
15utc_midnight = datetime.combine(d, time(0, 0), tzinfo=ZoneInfo("UTC"))
16print(utc_midnight.timestamp())  # 1758672000.0

The same calendar date corresponds to different UTC timestamps depending on the timezone.

Pandas Integration

python
1import pandas as pd
2
3# Date to timestamp
4d = pd.Timestamp("2025-09-24", tz="UTC")
5print(d.timestamp())  # 1758672000.0
6
7# Series of dates to timestamps
8dates = pd.to_datetime(["2025-09-24", "2025-09-25", "2025-09-26"])
9dates_utc = dates.tz_localize("UTC")
10timestamps = dates_utc.astype("int64") // 10**9  # Nanoseconds to seconds
11print(timestamps.values)  # [1758672000 1758758400 1758844800]

Epoch Reference

python
1from datetime import date, datetime, timezone
2
3# The Unix epoch
4epoch = date(1970, 1, 1)
5dt = datetime.combine(epoch, datetime.min.time(), tzinfo=timezone.utc)
6print(dt.timestamp())  # 0.0
7
8# Dates before the epoch produce negative timestamps
9old_date = date(1969, 7, 20)  # Moon landing
10dt = datetime.combine(old_date, datetime.min.time(), tzinfo=timezone.utc)
11print(dt.timestamp())  # -14182400.0

Common Pitfalls

  • Naive datetime assumes local time: datetime.combine(d, time()).timestamp() uses the system's local timezone, not UTC. Always pass tzinfo=timezone.utc explicitly.
  • Date boundary errors: A timestamp of 1758672000 (midnight UTC Sep 24) becomes Sep 23 at 7 PM in US Eastern. Always specify UTC when converting timestamps back to dates.
  • datetime.utcnow() is not UTC-aware: Despite the name, datetime.utcnow() returns a naive datetime. Use datetime.now(timezone.utc) instead (Python 3.2+).
  • DST ambiguity: During the fall-back DST transition, the same local time occurs twice. Using mktime() during this period may produce the wrong timestamp. UTC has no DST.
  • 32-bit timestamp overflow: Timestamps stored as 32-bit integers overflow on January 19, 2038. Use 64-bit integers or Python's arbitrary-precision int.

Summary

  • Use datetime.combine(d, time(), tzinfo=timezone.utc).timestamp() for date-to-UTC-timestamp
  • Use calendar.timegm(d.timetuple()) as an alternative that always treats input as UTC
  • Never use time.mktime() for UTC conversions because it uses local time
  • Always pass tz=timezone.utc to datetime.fromtimestamp() when converting back
  • The same calendar date maps to different timestamps in different timezones
  • Use int(ts * 1000) for millisecond timestamps (JavaScript/Java-style)

Course illustration
Course illustration

All Rights Reserved.