iKit
Tutorial · 10 min read ·

Convert a Date to Unix Timestamp: Bash, Python, JS, SQL (2026)

Convert any date to a Unix timestamp in Bash, Python, JavaScript, and SQL with copy-paste one-liners — plus the timezone trap each language hides.

Convert a Date to Unix Timestamp: Bash, Python, JS, SQL (2026)

Convert a Date to Unix Timestamp in Bash, Python, JavaScript, and SQL

You have a date — 2026-06-11 00:00:00 — and you need it as a Unix timestamp. The conversion takes one line in any language, but each language hides a different default: GNU date assumes local time, Python's naive datetimes call mktime(), JavaScript hands back milliseconds, and MySQL consults the session timezone. This guide gives you the one-liner for each, side by side, with the verified output so you can spot when yours disagrees.

TL;DR

  • Bash (Linux): date -u -d "2026-06-11 00:00:00" +%s1781136000
  • Python: datetime(2026, 6, 11, tzinfo=timezone.utc).timestamp()
  • JavaScript returns milliseconds — divide by 1000 before comparing.
  • SQL: Postgres extract(epoch from …), MySQL UNIX_TIMESTAMP(), SQLite unixepoch().
  • Strings without a timezone offset are the #1 source of mismatched results.

A Unix timestamp is the number of seconds since 1970-01-01 00:00:00 UTC, so the same instant yields the same number everywhere — when the input timezone is unambiguous. Every command below converts the same two test inputs: midnight UTC on 2026-06-11 (1781136000) and 2026-06-11T08:30:00+09:00 Tokyo time (1781134200). If you just want to paste a date and read the result, the Unix Timestamp Converter does the conversion in the browser, in both directions, with nothing uploaded.

How to convert a date to a Unix timestamp in Bash

The date command does it natively — but Linux and macOS ship two different date implementations with incompatible flags. Check which one you have before copying snippets from the internet.

GNU date on Linux: date -d with +%s

GNU coreutils date (Linux, Git Bash, WSL) parses almost any date string passed to -d and the +%s format prints epoch seconds:

date -u -d "2026-06-11 00:00:00" +%s
# 1781136000

The -u flag matters. Per the GNU coreutils date examples, when the date string carries no timezone information, date interprets it using the computer's idea of the local timezone — so the same command prints a different number in Berlin than in Denver. Either pass -u to force UTC, or put the offset in the string itself:

date -d "2026-06-11T08:30:00+09:00" +%s
# 1781134200

With an explicit offset in the input, -u is no longer needed — the string already pins the instant.

BSD date on macOS: date -j -f

macOS ships BSD date, where -d means something entirely different (it sets daylight-saving handling). The equivalent conversion uses -j (don't set the clock) and -f (input format):

date -j -u -f "%Y-%m-%d %H:%M:%S" \
  "2026-06-11 00:00:00" +%s
# 1781136000

The -f pattern must match the input string exactly, field for field. This is the most common reason a snippet "works on the server but not on my Mac" — the two date binaries simply have different flag sets, as documented in the date(1) manual page.

Converting a timestamp back to a date

Going the other way is worth knowing for spot checks. GNU date accepts @ followed by epoch seconds:

date -u -d @1781136000 +"%F %T %z"
# 2026-06-11 00:00:00 +0000

On macOS, the same role is played by -r: date -u -r 1781136000.

How to convert a date to a Unix timestamp in Python

Python's datetime is explicit about timezones — as long as you are. The dangerous path is the convenient-looking one.

Why datetime.timestamp() depends on your machine's timezone

datetime.timestamp() returns a float of epoch seconds. But the Python datetime documentation is blunt about naive instances: they "are assumed to represent local time," and the conversion goes through the platform's C mktime(). Attach a timezone and the ambiguity disappears:

from datetime import datetime, timezone

dt = datetime(2026, 6, 11, tzinfo=timezone.utc)
print(int(dt.timestamp()))
# 1781136000

Without tzinfo=timezone.utc, that script prints 1781136000 only on machines whose system timezone is UTC. On a laptop set to America/New_York it prints 1781150400 — four hours later — with no warning. If your code follows the "naive datetimes are UTC" convention, convert with dt.replace(tzinfo=timezone.utc).timestamp() rather than calling timestamp() directly.

Parsing ISO 8601 strings with fromisoformat()

When the date arrives as a string, fromisoformat() parses it — and if the string carries an offset, the resulting datetime is aware and converts correctly with no extra work:

from datetime import datetime

s = "2026-06-11T08:30:00+09:00"
print(int(datetime.fromisoformat(s).timestamp()))
# 1781134200

Strings without an offset come back naive, which drops you straight into the local-time trap above. Validate that dt.tzinfo is not None before trusting the result in any code that runs on more than one machine.

time.time() for the current moment

For "now" rather than a specific date, skip datetime entirely:

import time
print(int(time.time()))

time.time() returns the current epoch seconds as a float; int() truncates the sub-second part. This is the value you'll most often compare against expiry fields in tokens and cache entries.

How to get a Unix timestamp in JavaScript

JavaScript is the odd one out: every timestamp it produces is in milliseconds.

Date.now() returns milliseconds, not seconds

Per MDN's Date.now() reference, the method "returns the number of milliseconds elapsed since the epoch." To get a Unix timestamp comparable with Bash, Python, or SQL output, divide and floor:

Math.floor(Date.now() / 1000);
// e.g. 1781136000

Skipping the Math.floor leaves a fractional second in the value, which serializes as something like 1781136000.123 and breaks integer-typed fields downstream.

Converting a date string with getTime()

For a specific date, construct a Date and call getTime() — again milliseconds, again divide:

const d = new Date("2026-06-11T08:30:00+09:00");
Math.floor(d.getTime() / 1000);
// 1781134200

String parsing has its own subtlety: a date-only string like "2026-06-11" is parsed as UTC midnight, while a date-time string without an offset, like "2026-06-11T08:30:00", is parsed as local time. Always include the offset (Z or +09:00) in strings you generate, and treat offset-less strings from elsewhere as suspect.

Date.UTC() when you have components, not strings

If you hold year, month, and day as numbers, Date.UTC() avoids string parsing entirely — but months are zero-indexed, so June is 5:

Math.floor(Date.UTC(2026, 5, 11) / 1000);
// 1781136000

This is the safest JavaScript path: no string ambiguity, explicit UTC, one divide.

How to convert a date to a Unix timestamp in SQL

Each engine has its own function and — more importantly — its own timezone assumption for the input.

PostgreSQL: extract(epoch from timestamptz)

Postgres exposes epoch as a field of extract(). For timestamp with time zone values it returns the seconds since 1970-01-01 00:00:00 UTC, with fractional precision:

SELECT extract(
  epoch from timestamptz '2026-06-11 00:00:00+00'
)::bigint;
-- 1781136000

The ::bigint cast is deliberate: since Postgres 14 the raw result is numeric (it was double precision before), and an integer is what most schemas and drivers expect. Beware of extracting epoch from a plain timestamp (no zone): Postgres then returns the nominal seconds for the literal value "without regard to timezone," which silently changes meaning between columns.

MySQL: UNIX_TIMESTAMP() and the session time zone

MySQL's function takes the date directly:

SELECT UNIX_TIMESTAMP('2026-06-11 00:00:00');

The catch sits in the MySQL reference manual's timezone notes: UNIX_TIMESTAMP() assumes its argument is a datetime value in the session time zone. The query above returns 1781136000 only when time_zone is +00:00; under the common default of system time, the result follows whatever the server's OS is set to. Pin it explicitly in code that must be portable: SET time_zone = '+00:00'; before converting.

SQLite: unixepoch() and strftime('%s')

SQLite has had strftime('%s', …) forever and a dedicated unixepoch() function in recent versions. Per the SQLite date and time functions documentation, unixepoch() returns an integer and is equivalent to CAST(strftime('%s', …) AS INT):

SELECT unixepoch('2026-06-11 00:00:00');
-- 1781136000

SQLite's date functions work in UTC internally, so an offset-less string is treated as UTC — the opposite default from GNU date, Python, and MySQL. A trailing Z is a no-op; an explicit +09:00 suffix is subtracted to compute UTC, so unixepoch('2026-06-11 08:30:00+09:00') returns 1781134200. To interpret a string as local time instead, append the 'utc' modifier.

Same date, four languages: the side-by-side table

All commands below convert 2026-06-11 00:00:00 UTC and were verified to return 1781136000.

Tool One-liner Input TZ default
Bash (GNU) date -u -d "2026-06-11 00:00:00" +%s Local (-u forces UTC)
Python datetime(2026,6,11,tzinfo=timezone.utc).timestamp() Local if naive
JavaScript Date.UTC(2026, 5, 11) / 1000 UTC for date-only strings
SQL unixepoch(…) / extract(epoch …) / UNIX_TIMESTAMP(…) UTC / column type / session

The timezone trap that breaks parity

Notice the third column: it's different in every row. When two systems disagree about a converted date, the cause is almost always one of these:

  • Offset-less input strings. GNU date, Python naive datetimes, and MySQL read them as local/session time; SQLite and JavaScript date-only strings read them as UTC.
  • The server's timezone isn't yours. CI runners are usually UTC; laptops aren't. Code that passes locally and fails in CI (or vice versa) by a round number of hours has a timezone default leaking in.
  • DST boundaries. A local-time interpretation shifts by an hour twice a year, so a bug can hide for months and surface in March.

The fix is the same everywhere: carry the offset in the data (+09:00, Z) or force UTC at the conversion site (-u, tzinfo=timezone.utc, Date.UTC, SET time_zone = '+00:00').

Seconds vs milliseconds: the 1000× check

A quick sanity rule before you debug anything else: in 2026, epoch seconds are 10 digits (1781136000) and milliseconds are 13 digits (1781136000000). JavaScript is the only language on this page that deals in milliseconds natively, and JWT exp and iat claims are defined in seconds — which is why comparing Date.now() against a token expiry without dividing by 1000 makes every token look valid for another 50,000 years. If you work with tokens, the JWT Decoder shows exp and iat as both raw seconds and human-readable dates, and when you're staring at a bare 10- or 13-digit number from a log line, pasting it into the Unix Timestamp Converter settles the unit question instantly.

References

Related on iKit

Related posts