Decide the timezone and unit before converting
A calendar value becomes a Unix timestamp only after you answer two questions: which timezone does it belong to, and which unit does the consumer expect? For a fixed reference, 2026-06-20 09:25:00 UTC converts to 1781947500 Unix seconds or 1781947500000 Unix milliseconds. A different result means the parser used another timezone, another interpretation of the input, or another unit.
| Input | Meaning | Unix seconds |
|---|---|---|
| 2026-06-20 09:25 UTC | One UTC instant | 1781947500 |
| 2026-06-20 09:25 America/New_York | Same wall clock, Eastern daylight time | 1781961900 |
| 2026-06-20 09:25 Asia/Tokyo | Same wall clock, Japan time | 1781915100 |
| 2026-06-20 | Midnight at the start of the date in the chosen timezone | Depends on timezone |
Step 1: choose the timezone
A wall-clock date is not an instant unless it has a timezone. Use UTC for APIs, logs, queues, audit rows and cross-region systems. Only use a business or user timezone if the date is a local calendar event, such as store hours, a billing day, a renewal cutoff, or a scheduled reminder.
Step 2: convert to Unix seconds
Unix seconds are the default for shell commands, Python, PHP, Go, SQL epoch extraction, JWT claims, and many backend APIs. They are also easier to read in logs because modern values are 10 digits.
Step 3: keep milliseconds only when required
Use milliseconds for JavaScript Date, Java currentTimeMillis-style systems, browser analytics, and APIs that show 13-digit examples. Do not switch units in the middle of your app. Convert at the boundary and name the field with the unit.
What date to epoch conversion means
A Unix timestamp is a count from 1970-01-01 00:00:00 UTC. Date-to-epoch conversion runs from a human wall-clock value to that count. The hard part is not the arithmetic; it is choosing the exact instant the human date means.
These inputs look similar but are not equivalent:
- 2026-06-20 means the start of that calendar date in a chosen timezone.
- 2026-06-20 09:25 means a local wall-clock time, but it is incomplete without a timezone.
- 2026-06-20T09:25:00Z is already UTC and can be converted safely.
- 2026-06-20T09:25:00-04:00 has an explicit offset and maps to one instant.
- 1781947500 is already a Unix timestamp in seconds; do not convert it again.
Date in Unix timestamp form
When a search asks for a date in Unix timestamp form, the answer is the epoch integer for a specific boundary. "2026-06-20" by itself is not enough; you need "2026-06-20 at midnight UTC" or "2026-06-20 at midnight America/New_York."
Datetime Unix epoch
A datetime with a Z suffix, offset or IANA timezone maps to one epoch value cleanly. A datetime without a timezone is dependent on the machine, database session, spreadsheet, or runtime that parses it.
Timezone is part of the input
The most common date-to-epoch bug is to treat a local wall-clock value as if it were UTC. Then post-deployment, a release cut-off, coupon expiry or reporting window moves by hours. The math is correct. If the value was from user input, keep the user IANA timezone name. If it is from a web service or API contract, use UTC and make that clear from the field name/schema.
- Wrong: datetime(2026, 6, 20, 9, 25).timestamp() — Python uses the host timezone
- Right: datetime(2026, 6, 20, 9, 25, tzinfo=timezone.utc).timestamp() — explicit UTC
- Wrong: new Date('2026-06-20 09:25') — JavaScript parser falls back to local-time behavior
- Right: Date.UTC(2026, 5, 20, 9, 25) — UTC components; month index 5 means June
- Right: Date.parse('2026-06-20T09:25:00Z') — Z suffix pins UTC
- Right for local business time: store America/New_York, not just -04:00
UTC input
Use UTC when the generated Unix timestamp will cross services, logs, queues, databases or API consumers. The reference level is UTC.
Local business input
Report windows, store hours, subscription renewals, payroll cutoffs, and local calendar days in the business timezone. Remember the IANA name so that the correct future DST rules can be applied.
Seconds or milliseconds?
The output unit should be dictated by the consumer, not by preference. Seconds and milliseconds both represent the same instant, but mixing them is the fastest way to ship a date bug. The symptom is usually obvious: a date near 1970, or a date thousands of years in the future.
- 10 digits -> Unix seconds, such as 1781947500
- 13 digits -> Unix milliseconds, such as 1781947500000
- 16 digits -> microseconds, common in databases and event streams
- 19 digits -> nanoseconds, common in tracing and some high-precision systems
- Field names should include the unit: startsAtSeconds, scheduledAtMs, capturedAtMicros
Convert a date to a Unix timestamp in JavaScript
Use Date.UTC when you already have date parts that should be interpreted as UTC. It returns milliseconds, so divide by 1000 for Unix seconds. For strings, only parse ISO 8601 with a Z suffix or explicit offset. Avoid locale-looking strings such as 06/20/2026 because different runtimes can parse them differently.
- Date.UTC(2026, 5, 20, 9, 25) / 1000 // 1781947500 seconds; month index 5 = June
- Date.UTC(2026, 5, 20, 9, 25) // 1781947500000 milliseconds
- Math.floor(Date.parse('2026-06-20T09:25:00Z') / 1000) // ISO 8601 UTC
- Math.floor(Date.parse('2026-06-20T09:25:00-04:00') / 1000) // explicit offset
- Avoid: new Date('2026-06-20 09:25').getTime() / 1000 // runtime-local interpretation
- Temporal when available: Temporal.ZonedDateTime.from('2026-06-20T09:25-04:00[America/New_York]').epochSeconds
For UTC date-only input, construct midnight explicitly: Date.UTC(2026, 5, 20) / 1000. For a user timezone, use Temporal or a timezone library; classic Date has no clean built-in way to turn "9:25 in America/New_York" into an instant.
Convert a date to a Unix timestamp in Python
datetime in python.timestamp() is only correct if the datetime is timezone aware. Naive datetime is local time, so the same script can produce different epochs on a developer laptop, a Docker container, and a production host.
- from datetime import datetime, timezone
- datetime(2026, 6, 20, 9, 25, tzinfo=timezone.utc).timestamp() # 1781947500.0
- int(datetime(2026, 6, 20, 9, 25, tzinfo=timezone.utc).timestamp()) # 1781947500
- from zoneinfo import ZoneInfo
- int(datetime(2026, 6, 20, 9, 25, tzinfo=ZoneInfo('America/New_York')).timestamp()) # 1781961900
- Avoid: datetime(2026, 6, 20, 9, 25).timestamp() # host-local
- From ISO 8601: int(datetime.fromisoformat('2026-06-20T09:25:00+00:00').timestamp())
Use ZoneInfo for real user or business time zones Fixed offsets are fine for single-use timestamps, but they do not have any daylight saving rules.
Convert a date to a Unix timestamp in PHP
PHP’s time APIs are in seconds by default. strtotime() is convenient, but bare strings inherit the server timezone from php.ini or date_default_timezone_set() DateTimeImmutable with DateTimeZone makes the timezone visible in code and easy to review.
- strtotime('2026-06-20 09:25:00 UTC') // 1781947500
- (new DateTimeImmutable('2026-06-20 09:25:00', new DateTimeZone('UTC')))->getTimestamp()
- (new DateTimeImmutable('2026-06-20T09:25:00Z'))->getTimestamp()
- (new DateTimeImmutable('2026-06-20 09:25:00', new DateTimeZone('America/New_York')))->getTimestamp()
- Avoid: strtotime('2026-06-20 09:25:00') // server-timezone-dependent
- Sub-second input: DateTimeImmutable::createFromFormat('U.u', '1781947500.123456')
Convert a date to a Unix timestamp in Go
time. Go makes explicit the timezone and unit.The date of the location. Unix() returns seconds, UnixMilli(), UnixMicro(), and UnixNano() return finer units. This explicitness is handy in code review because the timezone and output unit are on the same line.
- time.Date(2026, time.June, 20, 9, 25, 0, 0, time.UTC).Unix() // 1781947500
- time.Date(2026, time.June, 20, 9, 25, 0, 0, time.UTC).UnixMilli() // 1781947500000
- loc, _ := time.LoadLocation("America/New_York")
- time.Date(2026, time.June, 20, 9, 25, 0, 0, loc).Unix() // 1781961900
- t, _ := time.Parse(time.RFC3339, "2026-06-20T09:25:00Z"); t.Unix()
- Sub-second: t.UnixMicro(), t.UnixNano()
Don’t ignore the error, now and then.LoadLocation or time.Parse in production code The examples drop it just to make the conversion line readable.
Convert a date to a Unix timestamp in shell on Linux or macOS
Linux and macOS both use +%s to print Unix seconds, but they do not parse input with the same flags. Most Linux distributions ship GNU date; macOS and FreeBSD ship BSD date; small Alpine and CI images may use a more limited BusyBox implementation.
| Environment | Common implementation | Date-parsing syntax |
|---|---|---|
| Ubuntu, Debian, Fedora, RHEL | GNU date |
date -d INPUT +%s |
| macOS and FreeBSD | BSD date |
date -j -f FORMAT INPUT +%s |
| Alpine and small containers | often BusyBox date |
option support varies; test the exact image |
| macOS with GNU coreutils | GNU gdate |
gdate -d INPUT +%s |
Make UTC explicit on GNU/Linux so the command returns the same value on a laptop, server and CI runner:
date -u -d '2026-06-20 09:25:00 UTC' +%s
# 1781947500
date -u -d '2026-06-20T09:25:00Z' +%s
# 1781947500
For a local business time, set its IANA timezone instead of relying on the host default:
TZ=America/New_York date -d '2026-06-20 09:25:00' +%s
# 1781961900
Avoid ambiguous inputs such as 06/20/26. An explicit order and timezone survive locale changes and are easier to review:
# Avoid: interpretation depends on locale and implementation
date -d '06/20/26' +%s
# Better: explicit order and timezone
date -u -d '2026-06-20 09:25:00 UTC' +%s
BSD date uses -j to parse without setting the system clock and -f to declare the input format:
date -j -u -f '%Y-%m-%d %H:%M:%S' '2026-06-20 09:25:00' +%s
# 1781947500
date -j -u -f '%Y-%m-%dT%H:%M:%SZ' '2026-06-20T09:25:00Z' +%s
# 1781947500
If a macOS script needs GNU syntax, install GNU coreutils and call gdate rather than assuming the system date understands -d.
Get the current Unix timestamp in shell
Current Unix seconds are portable across GNU and BSD implementations:
date +%s
GNU date can append the first three nanosecond digits for current milliseconds:
date +%s%3N
That is not portable to macOS: BSD date may print a literal 3N suffix because %N is a GNU extension. Use Python, Node.js, or gdate when a cross-platform script needs current epoch milliseconds.
For production logs, keeping a readable UTC value next to the epoch makes incidents easier to inspect:
now_s=$(date +%s)
now_iso=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
printf 'time=%s epoch=%s event=%s\n' "$now_iso" "$now_s" 'job_started'
Build date ranges without double-counting midnight
When the timestamps define a reporting or SQL boundary, use a half-open range:
start=$(date -u -d '2026-07-01 00:00:00 UTC' +%s)
end=$(date -u -d '2026-08-01 00:00:00 UTC' +%s)
printf 'created_at >= %s AND created_at < %s\n' "$start" "$end"
The exclusive upper bound keeps an event at exactly midnight from appearing in two adjacent periods.
GNU Coreutils date manual · Linux date(1) manual · FreeBSD date(1) manual
Convert a date to a Unix timestamp in SQL
SQL conversion is based on column type and session time zone The safest form is PostgreSQL TIMESTAMPTZ as it is an instant. The MySQL DATETIME type has no timezone of its own. It’s the session time_zone setting that matters. For migrations and reports, pin the timezone in the query instead of a connection default.
- PostgreSQL: SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '2026-06-20 09:25:00+00')::BIGINT; // 1781947500
- PostgreSQL column: SELECT EXTRACT(EPOCH FROM created_at)::BIGINT FROM events;
- MySQL UTC session: SET time_zone = '+00:00'; SELECT UNIX_TIMESTAMP('2026-06-20 09:25:00');
- MySQL named/local source: SELECT UNIX_TIMESTAMP(CONVERT_TZ('2026-06-20 09:25:00', 'America/New_York', '+00:00')); // requires timezone tables
- SQLite: SELECT strftime('%s', '2026-06-20T09:25:00Z');
- BigQuery: SELECT UNIX_SECONDS(TIMESTAMP '2026-06-20 09:25:00 UTC');
- BigQuery milliseconds: SELECT UNIX_MILLIS(TIMESTAMP '2026-06-20 09:25:00 UTC');
- ClickHouse: SELECT toUnixTimestamp(toDateTime('2026-06-20 09:25:00', 'UTC'));
Do not re-parse a database value that is already a Unix integer column with timestamp parsing. Check first whether the column is storing seconds, milliseconds or microseconds.
If MySQL CONVERT_TZ returns NULL for a named timezone, the server's timezone tables have not been loaded. If so, convert the local wall-clock value in application code with an IANA-aware library or load the MySQL timezone tables before relying on named zones.
Convert a date to a Unix timestamp in Excel
Excel stores dates as serial day numbers. If A1 contains a real Excel date/time value, subtract the Excel serial value for 1970-01-01 and multiply by seconds per day. This works for imported CSV dates, manual date cells, and formulas that return dates. It does not know the timezone, so label the source timezone in your sheet.
- Seconds: =(A1 - DATE(1970,1,1)) * 86400
- Integer seconds: =INT((A1 - DATE(1970,1,1)) * 86400)
- Milliseconds: =(A1 - DATE(1970,1,1)) * 86400000
- Microseconds: =(A1 - DATE(1970,1,1)) * 86400000000
- Reverse direction: =A1/86400 + DATE(1970,1,1)
- Format the result as Number, not Date
Example: if A1 is 2026-06-20 09:25 and you intend that value to mean UTC, the seconds formula should give 1781947500. If it does not, check whether A1 is text rather than a real Excel date.
Convert a date to a Unix timestamp in Google Sheets
Google Sheets also uses date serial numbers, so the Excel formula will work. Date to epoch : use the formula directly. Google sheets has EPOCHTODATE for the reverse direction . But the date to epoch path is still serial date math .
- Seconds: =(A1 - DATE(1970,1,1)) * 86400
- Integer seconds: =INT((A1 - DATE(1970,1,1)) * 86400)
- Milliseconds: =(A1 - DATE(1970,1,1)) * 86400000
- Microseconds: =(A1 - DATE(1970,1,1)) * 86400000000
- If A1 is text, parse it first with DATEVALUE / TIMEVALUE or import it as a date column
- Check File -> Settings -> Time zone before using NOW(), TODAY(), or locally entered date/time values
For the reverse task, Google documents EPOCHTODATE(timestamp, unit), where unit 1 is seconds, 2 is milliseconds, and 3 is microseconds.
Wall-clock to instant: DST gap and overlap handling
The hard direction is going from a local wall-clock time to a Unix timestamp. Most local times are a single instant. Some local times are zero instants, some are two, around daylight-saving boundaries. If your product sets reminders, renewals, cron-like jobs, or local cutoffs, pick and document a policy.
- Spring-forward gap: a wall-clock value that does not exist, such as 2026-03-08 02:30 in America/New_York.
- Fall-back overlap: a wall-clock value that happens twice, such as 2026-11-01 01:30 in America/New_York.
- Earlier overlap example: 2026-11-01T01:30:00-04:00 -> 1793511000.
- Later overlap example: 2026-11-01T01:30:00-05:00 -> 1793514600.
- Product policy: reject impossible times, or choose earlier/later explicitly.
- Storage policy: store the UTC epoch plus the IANA timezone when the local meaning matters later.
Pre-store checklist
Before storing the result, check the source timezone, output unit, DST behavior, and field name. This is the small checklist that catches the bugs that only show up after deploying on a different server.
Quick reference: date to epoch by tool
Use this section when you already know the input timezone and just need the right syntax. The examples all use 2026-06-20 09:25 UTC and return 1781947500 seconds unless noted.
| Tool | Unix seconds example | Notes |
|---|---|---|
| JavaScript | Date.UTC(2026, 5, 20, 9, 25) / 1000 | Month index is zero-based |
| Python | int(datetime(2026, 6, 20, 9, 25, tzinfo=timezone.utc).timestamp()) | Never use naive datetime |
| PHP | strtotime('2026-06-20 09:25:00 UTC') | Prefer DateTimeImmutable for app code |
| Go | time.Date(2026, time.June, 20, 9, 25, 0, 0, time.UTC).Unix() | Location is explicit |
| Linux shell | date -u -d '2026-06-20 09:25:00' +%s | GNU date |
| macOS shell | date -j -u -f '%Y-%m-%d %H:%M:%S' '2026-06-20 09:25:00' +%s | BSD date |
| PostgreSQL | EXTRACT(EPOCH FROM TIMESTAMPTZ '2026-06-20 09:25:00+00')::BIGINT | Prefer TIMESTAMPTZ |
| MySQL | SET time_zone = '+00:00'; SELECT UNIX_TIMESTAMP('2026-06-20 09:25:00'); | Session timezone matters |
| Excel | =(A1 - DATE(1970,1,1)) * 86400 | A1 must be a real date cell |
| Google Sheets | =(A1 - DATE(1970,1,1)) * 86400 | Check sheet timezone for entered dates |
Frequent questions:
- Q: How do I convert a date to a Unix epoch?
- A: Choose the timezone first, then parse the date in that timezone and extract Unix seconds or milliseconds. Example: 2026-06-20 09:25 UTC is 1781947500 seconds. JavaScript: Date.UTC(2026, 5, 20, 9, 25) / 1000. Python: datetime(2026, 6, 20, 9, 25, tzinfo=timezone.utc).timestamp(). Shell: date -u -d '2026-06-20 09:25:00' +%s.
- Q: What does date to epoch mean?
- A: It means turning a readable calendar value such as 2026-06-20 09:25 UTC into the Unix timestamp for that instant. Unix seconds count from 1970-01-01 00:00:00 UTC. Unix milliseconds use the same epoch but multiply the seconds value by 1000.
- Q: Does date to epoch use UTC?
- A: The epoch count is UTC-based, but your input date may be UTC or a local wall-clock time. A date-only input such as 2026-06-20 means midnight in whichever timezone you choose. For APIs, logs, and database storage, choose UTC unless the value is explicitly a local business time.
- Q: Why does the same date give a different epoch in different timezones?
- A: Because a wall-clock date is not a single instant until it has a timezone. 2026-06-20 09:25 in UTC is 1781947500. The same wall-clock time in America/New_York is 1781961900, and in Asia/Tokyo it is 1781915100.
- Q: Why does my Python datetime give the wrong epoch?
- A: Usually because the datetime is timezone-naive. Python treats a naive datetime as local time when you call .timestamp(), so a laptop and a UTC server can produce different values. Use tzinfo=timezone.utc or ZoneInfo('America/New_York') before converting.
- Q: How do I convert a date to epoch in JavaScript?
- A: For a UTC component date, use Date.UTC(year, monthIndex, day, hour, minute) and divide by 1000 for seconds. Remember that monthIndex is zero-based: June is 5. For ISO strings, parse only strings with Z or an explicit offset, such as 2026-06-20T09:25:00Z.
- Q: Should I output epoch seconds or milliseconds?
- A: Match the receiving system. Unix tools, Python, PHP, SQL, and many backend APIs usually expect seconds. JavaScript Date, Java currentTimeMillis-style code, browser analytics, and some event streams expect milliseconds. Put the unit in the field name: scheduledAtSeconds or scheduledAtMs.
- Q: How do I convert a date to a Unix timestamp in Excel?
- A: If A1 is a real Excel date/time value, use =(A1 - DATE(1970,1,1)) * 86400 for Unix seconds, or multiply by 86400000 for milliseconds. Format the result cell as Number, not Date. Excel formulas are not timezone-aware, so label the intended timezone in the column header.
- Q: How do I convert a date to a Unix timestamp in Google Sheets?
- A: Use the same serial-date formula: =(A1 - DATE(1970,1,1)) * 86400 for seconds, or multiply by 86400000 for milliseconds. Google Sheets has EPOCHTODATE for the reverse direction, but date-to-epoch is best done with the formula.
- Q: How do I handle DST when converting a local date to epoch?
- A: Use an IANA timezone and a zone-aware API. Some wall-clock times do not exist during spring-forward, and some happen twice during fall-back. Decide whether your product should reject the ambiguous time or choose the earlier or later instant.
- Q: Is timestamp to epoch the same as date to epoch?
- A: If the timestamp is already a 10-digit Unix integer, it is already epoch seconds. If it is a 13-digit value, it is usually epoch milliseconds. If it is a database TIMESTAMP or TIMESTAMPTZ value, extract the epoch with EXTRACT(EPOCH FROM col), UNIX_TIMESTAMP(col), or the equivalent database function.