← All posts

Date to Epoch: Convert Time or Datetime to Unix Timestamp

To convert a date to epoch, choose the timezone for the wall-clock value, parse it as a real instant, then output Unix seconds or milliseconds. UTC is safest for APIs and logs; local business time is better for billing days or schedules.

Date to epoch in one line

Here is the whole workflow: choose the timezone, parse the date in that zone, then return Unix seconds or milliseconds. For 2026-06-20 09:25 UTC, JavaScript uses Date.UTC(2026, 5, 20, 9, 25) / 1000, Python uses datetime(2026, 6, 20, 9, 25, tzinfo=timezone.utc).timestamp(), and Linux uses date -u -d '2026-06-20 09:25:00' +%s.

Step 1: choose the timezone

A wall-clock date is not an instant until it has a timezone. Use UTC for backend logs and APIs; use a business or user timezone for local calendar boundaries.

Step 2: convert to Unix seconds

Most command-line tools, databases, and backend languages return epoch seconds. Use integer seconds when the receiving system does not need sub-second precision.

Step 3: keep milliseconds only when required

JavaScript Date, browser analytics, Java, and .NET commonly use milliseconds. Keep the unit in the field name, such as expiresAtMs or createdAtSeconds.

What date to epoch conversion means

A Unix timestamp is the count of seconds since 1970-01-01 UTC. To convert a date to a Unix timestamp you pick the timezone the wall-clock represents, then ask your language for the epoch. The integer that comes out is timezone-neutral — it represents one exact instant in time. The chosen IANA zone only affects which wall-clock value maps to which instant. This is the inverse of decoding a Unix timestamp back to a date — the math is the same, just running in the opposite direction.

Date in Unix timestamp form

When a search asks for a date in Unix timestamp form, the answer is the integer epoch value for that date at a specific timezone boundary.

Datetime Unix epoch

A datetime with an offset or IANA zone maps cleanly to one epoch value. A datetime without a zone depends on the machine that parses it.

Timezone is part of the input

The single biggest source of date-to-epoch bugs is forgetting that a wall-clock date isn't a moment in time — it's a moment in time plus a timezone. '2026-06-20 09:25' in America/New_York and '2026-06-20 09:25' in Asia/Tokyo are 13 hours apart, mapping to two different Unix timestamps. Languages that silently interpret a naive date as 'local time' produce different epochs on every host. The fix is to always pass the timezone explicitly, even when it's UTC.

  • Wrong: datetime(2026, 6, 20, 9, 25).timestamp() — Python interprets as local time
  • Right: datetime(2026, 6, 20, 9, 25, tzinfo=timezone.utc).timestamp() — explicit UTC
  • Wrong: new Date('2026-06-20 09:25') — JavaScript interprets as local time
  • Right: Date.UTC(2026, 5, 20, 9, 25) — month is 0-indexed; returns ms since epoch
  • Right: Date.parse('2026-06-20T09:25:00Z') — Z suffix forces UTC

UTC input

Use UTC when the generated Unix timestamp will move between services, logs, queues, or databases.

Local business input

Use the business timezone for reporting windows, store hours, subscription renewals, and local calendar days.

Seconds or milliseconds?

JavaScript Date.now() and Date.getTime() return milliseconds. Java Instant.toEpochMilli() returns milliseconds. Almost everything else — Python, PHP, Go, Linux date, every Unix tool — returns seconds by default. When seconds and milliseconds mix at a system boundary, the symptom is dates off by a factor of 1000 in one direction. Pick a side and stick to it inside any one system; convert only at the boundary; and put the unit in the field name.

  • 10-digit number → Unix seconds (around 1.7×10^9 in 2026)
  • 13-digit number → Unix milliseconds (around 1.7×10^12 in 2026)
  • 16-digit number → Unix microseconds (around 1.7×10^15 in 2026)
  • Document the unit in the field name: createdAtMs vs createdAtSeconds vs expiresAtMicros
  • Convert at the boundary: divide by 1000 on the way in, multiply by 1000 on the way out

Convert a date to a Unix timestamp in JavaScript

JavaScript has two main paths. For literal date components, Date.UTC(year, monthIndex, day, ...) returns milliseconds since the epoch without involving any timezone — perfect when you already know the value is in UTC. For arbitrary strings, Date.parse() works only when the string is a full ISO 8601 with a Z or offset suffix; never trust it with locale-formatted strings like '06/20/2026'. Divide by 1000 to get Unix seconds.

  • Date.UTC(2026, 5, 20, 9, 25) / 1000 // months are 0-indexed: 5 = June; returns Unix seconds
  • Date.UTC(2026, 5, 20, 9, 25) // returns Unix milliseconds (no division)
  • Date.parse('2026-06-20T09:25:00Z') / 1000 // ISO 8601 with Z suffix
  • Date.parse('2026-06-20T09:25:00-05:00') / 1000 // explicit offset
  • new Date(year, monthIndex, day).getTime() // local-tz; almost always wrong server-side
  • Modern: Temporal.ZonedDateTime.from('2026-06-20T09:25-05:00[America/New_York]').epochSeconds

Convert a date to a Unix timestamp in Python

Python's canonical conversion is datetime(...).timestamp() — but only when the datetime is timezone-aware. Naive datetimes are silently treated as local time, so a script that runs on a developer's laptop and a production server in UTC produces two different epochs. Always construct with tzinfo=timezone.utc or attach a ZoneInfo before calling .timestamp(). The result is a float of Unix seconds; cast to int if you want second precision.

  • from datetime import datetime, timezone
  • datetime(2026, 6, 20, 9, 25, tzinfo=timezone.utc).timestamp() # explicit UTC
  • int(datetime(2026, 6, 20, 9, 25, tzinfo=timezone.utc).timestamp()) # second precision
  • from zoneinfo import ZoneInfo
  • datetime(2026, 6, 20, 9, 25, tzinfo=ZoneInfo('America/New_York')).timestamp() # zone-aware
  • Avoid: datetime(2026, 6, 20, 9, 25).timestamp() # naive — interpreted as local time
  • From ISO 8601: int(datetime.fromisoformat('2026-06-20T09:25:00+00:00').timestamp())

Convert a date to a Unix timestamp in PHP

PHP's strtotime() parses a wide range of date strings into Unix seconds — but it interprets bare strings as the server's timezone, controlled by date_default_timezone_set or php.ini. The DateTime + DateTimeZone APIs are the modern, explicit replacement; getTimestamp() returns Unix seconds regardless of the input zone. Always pass the @ prefix or a Z-suffixed ISO 8601 string when you want UTC unambiguously.

  • strtotime('2026-06-20 09:25:00 UTC') // returns Unix seconds; UTC suffix forces zone
  • (new DateTime('2026-06-20 09:25:00', new DateTimeZone('UTC')))->getTimestamp()
  • (new DateTime('2026-06-20T09:25:00Z'))->getTimestamp() // ISO 8601 with Z
  • (new DateTime('@1750409100'))->getTimestamp() // @ prefix is Unix seconds in, out
  • Avoid: strtotime('2026-06-20') // server-timezone-dependent
  • Sub-second: DateTime::createFromFormat('U.u', '1750409100.123456')

Convert a date to a Unix timestamp in Go

Go's time package is the most explicit of any major language: every time.Time carries its location, and time.Date() requires you to pass one. time.UTC, time.Local, and time.LoadLocation('America/New_York') are the three common forms. Unix() returns seconds, UnixMilli() returns milliseconds, UnixMicro() returns microseconds, UnixNano() returns nanoseconds — Go forces you to pick the unit, which eliminates the silent unit-drift bug at the cost of a slightly longer line.

  • time.Date(2026, time.June, 20, 9, 25, 0, 0, time.UTC).Unix() // Unix seconds
  • time.Date(2026, time.June, 20, 9, 25, 0, 0, time.UTC).UnixMilli() // milliseconds
  • loc, _ := time.LoadLocation("America/New_York")
  • time.Date(2026, time.June, 20, 9, 25, 0, 0, loc).Unix() // zone-aware
  • time.Parse(time.RFC3339, "2026-06-20T09:25:00Z") // returns time.Time
  • Sub-second: t.UnixMicro(), t.UnixNano() — pick the unit explicitly

Convert a date to a Unix timestamp in shell (Linux / macOS)

On Linux the GNU date command parses a wide range of date strings with -d; the +%s format directive prints Unix seconds. On macOS the BSD date command uses -j -f to parse with an explicit format, then +%s for the output. The flags differ by historical implementation — the underlying epoch math is identical. Use the -u flag (or TZ=UTC) to force UTC parsing regardless of the system timezone.

  • GNU (Linux): date -u -d '2026-06-20 09:25:00' +%s // Unix seconds
  • GNU: date -u -d '2026-06-20T09:25:00Z' +%s // ISO 8601 with Z
  • GNU: date -u -d 'now' +%s // current Unix seconds
  • BSD (macOS): date -j -u -f '%Y-%m-%d %H:%M:%S' '2026-06-20 09:25:00' +%s
  • BSD: date -j -u -f '%Y-%m-%dT%H:%M:%SZ' '2026-06-20T09:25:00Z' +%s
  • Both: prefix with TZ=America/New_York to interpret the input in a specific zone

Convert a date to a Unix timestamp in SQL (Postgres, MySQL, SQLite, BigQuery)

Every major SQL dialect has a built-in for extracting the Unix epoch from a date or timestamp value. The function name varies but the result is the same — Unix seconds (or milliseconds in BigQuery's case). Always extract from a TIMESTAMPTZ in Postgres, or a UTC-typed column elsewhere, so the result is the actual instant rather than a session-timezone interpretation.

  • PostgreSQL: EXTRACT(EPOCH FROM TIMESTAMPTZ '2026-06-20 09:25:00+00') // returns float seconds
  • PostgreSQL: EXTRACT(EPOCH FROM col)::BIGINT // int seconds from a column
  • MySQL: UNIX_TIMESTAMP('2026-06-20 09:25:00') // session-tz-aware; pin with CONVERT_TZ
  • MySQL: UNIX_TIMESTAMP(CONVERT_TZ('2026-06-20 09:25:00', '+00:00', '+00:00')) // force UTC
  • SQLite: strftime('%s', '2026-06-20 09:25:00') // returns Unix seconds as TEXT
  • BigQuery: UNIX_SECONDS(TIMESTAMP '2026-06-20 09:25:00 UTC')
  • BigQuery: UNIX_MILLIS(TIMESTAMP '2026-06-20 09:25:00 UTC')
  • ClickHouse: toUnixTimestamp(toDateTime('2026-06-20 09:25:00'))

Convert a date to a Unix timestamp in Excel

Excel stores dates as serial numbers — the count of days since 1900-01-01. Converting an Excel date to a Unix timestamp is just unit conversion in reverse: subtract the 1970-01-01 date serial and multiply by the seconds per day. The formula =(A1 - DATE(1970,1,1)) * 86400 gives Unix seconds. After entering the formula, format the result cell as Number (not Date) — otherwise Excel renders the integer as a year far in the future.

  • Seconds: =(A1 - DATE(1970,1,1)) * 86400 // when A1 holds a date value
  • Milliseconds: =(A1 - DATE(1970,1,1)) * 86400000
  • Microseconds: =(A1 - DATE(1970,1,1)) * 86400000000
  • Format result cell as Number (Ctrl+1 → Number → Number, 0 decimals)
  • Caveat: Excel dates are stored in the workbook's locale-displayed but UTC-neutral form
  • Reverse direction (Unix to date): =A1/86400 + DATE(1970,1,1), see /blog/unix-time-to-date

Convert a date to a Unix timestamp in Google Sheets

Google Sheets accepts the same canonical Excel formula and adds a dedicated DATETOEPOCH function. The shortcut form is =DATETOEPOCH(A1, 1), where the second argument is the unit code: 1 for seconds, 2 for milliseconds, 3 for microseconds. The result is anchored at UTC regardless of the sheet's locale settings — useful for tooling that ingests sheet exports.

  • =DATETOEPOCH(A1, 1) // seconds — shorthand
  • =DATETOEPOCH(A1, 2) // milliseconds
  • =DATETOEPOCH(A1, 3) // microseconds
  • =(A1 - DATE(1970,1,1)) * 86400 // canonical formula — works in Sheets too
  • For a date+time cell, the formula handles the fractional-day part automatically
  • Time zone applied: UTC (DATETOEPOCH); check sheet locale for the canonical formula

Wall-clock to instant: DST gap and overlap handling

Going from a wall-clock time in a given timezone to a Unix timestamp is the genuinely hard direction. Most of the time the wall-clock maps to exactly one instant — but on daylight-saving transition days, it can map to zero (spring-forward gap) or two (fall-back overlap). Zone-aware libraries surface this: Temporal raises if you ask for the impossible value, Python zoneinfo lets you pick first or last via the fold argument. Naive code (manual offset arithmetic, server-tz parsing) silently picks one and hides the ambiguity. Decide explicitly, or use a library that forces you to.

  • Spring-forward gap: a wall-clock value that doesn't exist (02:00-02:59 on 2026-03-08 US Eastern)
  • Fall-back overlap: a wall-clock value that exists twice (01:00-01:59 on 2026-11-01 US Eastern)
  • Temporal: ZonedDateTime.from(... { disambiguation: 'earlier' | 'later' | 'reject' })
  • Python: datetime(..., fold=0) for the earlier instance, fold=1 for the later
  • JavaScript naive: silent default; verify by inspecting the resulting Unix value
  • Site tool: /timezone gives you the wall-clock to instant mapping interactively

Pre-store checklist

Before storing the result, verify the input timezone, output unit, DST disambiguation, and field name. That quick check catches the bugs that only appear after a server runs in a different timezone.

FAQ

How do I convert a date to a Unix epoch?
Pick the timezone the date represents (almost always UTC), then call your language's epoch function. In JavaScript: Date.UTC(2026, 0, 1) / 1000. In Python: datetime(2026, 1, 1, tzinfo=timezone.utc).timestamp(). In shell: date -u -d '2026-01-01' +%s. The result is the same Unix seconds value in every language.
Why does my Python datetime give the wrong epoch?
Almost always because the datetime is timezone-naive. Python interprets a naive datetime as local time when you call .timestamp(), so the result depends on the host's timezone. Construct with tzinfo=timezone.utc, or attach a ZoneInfo before converting.
Do I need milliseconds for JavaScript?
Date.getTime() and Date.now() return milliseconds, and most browser and analytics APIs expect ms. Backend APIs, Unix tools, and many databases default to seconds. When in doubt, divide or multiply by 1000 and document the unit in the field name.
How do I handle DST when converting in code?
Use a zone-aware library — Python zoneinfo, JavaScript Temporal or Luxon, Go time.LoadLocation. They expose the spring-forward gap (a wall-clock that does not exist) and fall-back overlap (one that exists twice) instead of silently picking one.
Which language has the simplest date to epoch conversion?
Go and JavaScript are shortest when the input is already an RFC 3339 / ISO 8601 string with an offset — both reduce to a parse + one method call. Python and SQL need an explicit timezone choice before the conversion is safe.
Should I send epoch seconds or milliseconds to an API?
Match the documented unit of the receiving API. When you control both sides, milliseconds is the safer default — it matches JavaScript Date and Java Instant out of the box. Either way, name the field with the unit (createdAtMs, expiresAtSeconds) so the next reader doesn't have to guess.
How do I convert a date to a Unix timestamp in Excel?
Use =(A1 - DATE(1970,1,1)) * 86400 where A1 holds a date value. The result is Unix seconds. For milliseconds, multiply by 86,400,000 instead. Format the result cell as Number, not as a Date — Excel will otherwise render it as a year far in the future.
How do I convert a date to a Unix timestamp in Google Sheets?
Same canonical formula as Excel: =(A1 - DATE(1970,1,1)) * 86400 for seconds. Google Sheets also offers =DATETOEPOCH(A1, 1) where the second argument is the unit (1 seconds, 2 ms, 3 microseconds).
Why does the same date give a different epoch in different timezones?
Because a wall-clock date is only an instant when paired with a timezone. '2026-06-20 09:25' in America/New_York and '2026-06-20 09:25' in Asia/Tokyo are 13 hours apart — two different Unix timestamps. Specify the timezone in your input, or you'll get the host's local-time interpretation.
Is timestamp to epoch the same as date to epoch?
Yes when the timestamp is already a Unix integer — it's the same number. If the timestamp is a database column with TIMESTAMP / TIMESTAMPTZ semantics, extract the epoch with EXTRACT(EPOCH FROM col) in Postgres or UNIX_TIMESTAMP(col) in MySQL.
How do I convert timestamp to epoch?
If the timestamp is a readable date string, parse it with an explicit timezone and return Unix seconds. If it is already a 10-digit Unix integer, it is already epoch seconds; if it has 13 digits, divide by 1000 for epoch seconds.