JavaScript epoch/timestamp converter

Convert between Unix epoch values and JavaScript Date objects, with copyable code for both directions.

Converting timestamps in JavaScript

JavaScript represents every instant in time with a single built-in type, the Date object, and stores it internally as a count of milliseconds since 1970-01-01T00:00:00Z — a Unix timestamp, just in milliseconds instead of the seconds most other languages and Unix tools use. Date.now() hands you that count directly as a plain number, and new Date(ms) turns a millisecond count back into a full Date object with year, month, day, hour, minute and second all derived from it. In between, .getTime() pulls the millisecond count back out of an existing Date, and toISOString() renders that instant as a readable UTC string. These four calls cover the vast majority of timestamp work you will ever do in JavaScript: an API returns createdAt as an epoch number, a form needs to show it as a date, and a click handler needs to convert whatever the user typed back into a number for the next request. The conversions themselves are one-liners, but two details trip up even experienced JavaScript developers: the units mismatch between JavaScript's milliseconds and the seconds convention used almost everywhere else, and the fact that a Date has no timezone of its own — only the method you call to read it decides whether you see UTC or the browser's local time. Get either wrong and a timestamp that looks correct in the console will render as 1970, the far future, or a few hours off once real data reaches it. This page works through the calls you actually need, with runnable code for each direction and for the two gotchas that most often turn "just convert this number" into a debugging session before it does.

Get the current Unix timestamp

Date.now() returns the current epoch value directly, in milliseconds. There is no timezone to get wrong here — it is just a count of milliseconds since 1970 UTC.

const epochMs = Date.now()              // 1786795200123 (number, milliseconds)
const epochSeconds = Math.floor(Date.now() / 1000)  // 1786795200 (whole seconds)

Convert a Date to a Unix timestamp

Call .getTime() on a Date object, or use the unary plus operator — both return milliseconds. Divide by 1000 if the value needs to match a Unix API or a database column that stores seconds.

const date = new Date('2026-08-15T04:00:00Z')

const epochMs = date.getTime()          // 1786795200000
const epochMsShort = +date              // 1786795200000, same value
const epochSeconds = Math.floor(date.getTime() / 1000)  // 1786795200

Convert a Unix timestamp to a Date

Pass milliseconds to the Date constructor. Because JavaScript always works in milliseconds, a timestamp given in seconds — the more common convention outside JavaScript — has to be multiplied by 1000 first.

const epochSeconds = 1786795200

// Seconds must be multiplied by 1000 first
const date = new Date(epochSeconds * 1000)
console.log(date.toISOString())  // 2026-08-15T04:00:00.000Z

// A millisecond value goes in directly
const epochMs = 1786795200000
const sameDate = new Date(epochMs)

The modern replacement is Temporal, a Stage 3 TC39 proposal that has begun landing in browsers and has a maintained polyfill for everything else. Temporal.Instant is the type Date should have been — an exact instant with no timezone and no mutable setters — and it is the first API in the language that takes epoch seconds without asking you to remember the factor of 1000:

// Seconds and milliseconds each get their own constructor — no × 1000
const instant = Temporal.Instant.fromEpochSeconds(1786795200)
const sameInstant = Temporal.Instant.fromEpochMilliseconds(1786795200000)

instant.toString()                    // '2026-08-15T04:00:00Z'
instant.epochSeconds                  // 1786795200 — back out again, still seconds
instant.toZonedDateTimeISO('Asia/Kolkata').toString()
// '2026-08-15T09:30:00+05:30[Asia/Kolkata]'

The separate fromEpochSeconds and fromEpochMilliseconds constructors are the point: the seconds-versus-milliseconds bug this page keeps returning to exists because new Date(n) has one constructor and has to guess. If you are writing new code and can afford the polyfill, Temporal.Instant.fromEpochSeconds() deletes a whole class of bug rather than documenting it.

Handling timezones in JavaScript

A Date object always stores one instant internally as UTC milliseconds — it has no timezone attached to it. Whether you see UTC or local time depends entirely on which method reads it: toISOString() always renders UTC, toLocaleString() and getters like getHours() render the browser's local timezone, and passing a timeZone option renders any named zone you choose. To see what one instant looks like across several named zones at once, with the daylight-saving offset for that specific date already resolved, use the UTC-to-local timezone converter.

const date = new Date(1786795200000)

date.toISOString()                       // '2026-08-15T04:00:00.000Z' — always UTC
date.toLocaleString()                    // browser's local timezone
date.getUTCHours()                       // reads the UTC hour
date.getHours()                          // reads the LOCAL hour — different machine, different answer

date.toLocaleString('en-US', { timeZone: 'America/New_York' })
// renders the same instant in a specific named zone, regardless of the browser's own timezone

Common gotchas

Frequently asked questions

How do I get the current Unix timestamp in JavaScript?

Call Date.now(). It returns the current Unix timestamp in milliseconds since 1970-01-01T00:00:00Z, as a plain number. For seconds, divide by 1000 and floor the result: Math.floor(Date.now() / 1000).

How do I convert a JavaScript Date to a Unix timestamp?

Call .getTime() on the Date object, or use the unary plus operator: +date. Both return milliseconds since the epoch. Divide by 1000 if you need seconds to match a Unix API or database column.

How do I convert a Unix timestamp to a JavaScript Date?

Pass milliseconds to the Date constructor: new Date(epochMs). JavaScript's Date constructor always expects milliseconds, so a Unix timestamp given in seconds must be multiplied by 1000 first: new Date(epochSeconds * 1000).

Why is my JavaScript date off by 1000x or showing the wrong year?

Almost always a seconds/milliseconds mismatch. JavaScript's Date constructor and Date.now() both use milliseconds, but most other languages and Unix tools use seconds. Passing a raw seconds value into new Date() without multiplying by 1000 produces a date in 1970; passing a milliseconds value where seconds were expected produces a date far in the future.

How do I handle timezones in JavaScript?

A Date object always stores a single instant in UTC internally — it has no timezone of its own. toISOString() always renders that instant in UTC. toLocaleString() and getters like getHours() render or read it in the browser's local timezone. For a specific named timezone, pass a timeZone option to toLocaleString() or Intl.DateTimeFormat, e.g. { timeZone: 'America/New_York' }.

Where to go next

toISOString() is only half the story if the string is coming the other way: turning an ISO 8601 or RFC 3339 string back into epoch seconds is where a missing Z quietly shifts the result by your timezone's offset. And if the other end of the wire is a backend rather than a browser, the same conversion in Python works in seconds, which is why a value crossing between the two so often arrives 1000× off.