Unix timestamp converter: seconds, milliseconds, microseconds explained

timestamp unix developer-tools

Unix timestamp converter: seconds, milliseconds, microseconds explained

The Unix timestamp is one of those things that looks simple until you use it across languages and find out that JavaScript expects milliseconds, Python expects seconds, and your database expects something else entirely. This guide explains the three common units, how to convert between them, and the bugs that happen when you get it wrong.

Want to convert a timestamp right now without writing code? Use the free Timestamp Converter — supports seconds, milliseconds, microseconds, and nanoseconds, with timezone-aware output.


What a Unix timestamp is

A Unix timestamp is the number of seconds (or sub-seconds) that have elapsed since 1970-01-01 00:00:00 UTC, excluding leap seconds. This moment is called the Unix epoch.

The timestamp is always UTC. It has no timezone. When you display it as a human-readable date, you apply a timezone — but the timestamp itself is universal.

Three common units:

UnitMagnitudeUsed by
Seconds10 digits in 2026Python time.time(), C time(), most Unix tools
Milliseconds13 digits in 2026JavaScript Date.now(), Java System.currentTimeMillis()
Microseconds16 digits in 2026Python time.time_ns() / Go time.Now().UnixMicro()
Nanoseconds19 digits in 2026Go time.Now().UnixNano(), Python time.time_ns()

The rule of thumb: count the digits.

  • 10 digits → seconds (e.g. 1751328000 = 2026-07-01 00:00:00 UTC)
  • 13 digits → milliseconds (e.g. 1751328000000)
  • 16 digits → microseconds
  • 19 digits → nanoseconds
If you see a 10-digit number in a JS context, it is seconds. If you pass it directly to new Date(...), you get a date in 1970 — that is bug #1 below.


Converting between units

The conversions are powers of 1000:

1 second      = 1,000 milliseconds  = 1,000,000 microseconds  = 1,000,000,000 nanoseconds

Seconds → milliseconds (JS)

const seconds = 1751328000;
const ms = seconds * 1000;
const date = new Date(ms);

Milliseconds → seconds (Python)

import time
ms = 1751328000000
seconds = ms // 1000

Any unit → JS Date

JavaScript Date only accepts milliseconds. Convert first:

function toDate(timestamp, unit) {
  const multipliers = {
    s: 1000,
    ms: 1,
    us: 0.001,
    ns: 0.000001,
  };
  return new Date(timestamp * multipliers[unit]);
}

The three classic bugs

Bug 1: Passing seconds to JavaScript Date

new Date(1751328000);
// Thu Jan 21 1970 06:05:28 GMT+0000

JavaScript expects milliseconds. Multiply by 1000:

new Date(1751328000 * 1000);
// Wed Jul 01 2026 00:00:00 GMT+0000

Bug 2: Integer overflow with nanoseconds

JavaScript numbers are 64-bit floats, which can exactly represent integers up to 2^53 (about 9 quadrillion). A nanosecond timestamp in 2026 is around 1.7 trillion — well within range. But if you are doing arithmetic on nanosecond timestamps from multiple sources, you can lose precision.

Fix: use BigInt for nanosecond timestamps:

const ns = 1751328000000000000n;
const ms = Number(ns / 1_000_000n);
new Date(ms);

Bug 3: Timezone confusion when displaying

The timestamp is UTC. When you call toString() on a Date in JavaScript, it uses the runtime's local timezone. The same timestamp prints differently on a server in Tokyo vs a server in New York.

const ts = 1751328000000;
new Date(ts).toString();
// In Tokyo:  "Wed Jul 01 2026 09:00:00 GMT+0900"
// In New York: "Tue Jun 30 2026 20:00:00 GMT-0400"

This is correct — the timestamp is the same instant. But if you store the string representation and compare it later, you will get mismatches.

Fix: always store and transmit the numeric timestamp. Only convert to a string at the display layer, using an explicit timezone:

new Date(ts).toLocaleString('en-US', { timeZone: 'America/New_York' });

Or use toISOString() for a canonical UTC string:

new Date(ts).toISOString();
// "2026-07-01T00:00:00.000Z"

Language reference

JavaScript

Date.now();                    // milliseconds (number)
new Date().getTime();          // milliseconds (number)
new Date().toISOString();      // "2026-07-01T00:00:00.000Z"

Python

import time
from datetime import datetime, timezone

time.time() # seconds (float) time.time_ns() # nanoseconds (int) datetime.now(timezone.utc) # datetime object with tz datetime.now(timezone.utc).timestamp() # seconds (float)

Go

import "time"

time.Now().Unix() // seconds (int64) time.Now().UnixMilli() // milliseconds (int64) time.Now().UnixMicro() // microseconds (int64) time.Now().UnixNano() // nanoseconds (int64)

Java

System.currentTimeMillis();        // milliseconds (long)
Instant.now().getEpochSecond();    // seconds (long)
Instant.now().toEpochMilli();      // milliseconds (long)

SQL

-- Postgres
SELECT EXTRACT(EPOCH FROM NOW());        -- seconds (double precision)
SELECT EXTRACT(EPOCH FROM NOW()) * 1000; -- milliseconds

-- MySQL SELECT UNIX_TIMESTAMP(); -- seconds SELECT UNIX_TIMESTAMP() * 1000; -- milliseconds (as decimal)

-- SQLite SELECT strftime('%s', 'now'); -- seconds (text)


Timezones and display

The timestamp is UTC. To show it in a user's local time, you need to know their timezone. In a browser, the default is the user's system timezone:

new Date(1751328000000).toLocaleString();
// Uses the browser's local timezone automatically

On a server, the default is the server's timezone, which is usually not what you want. Always specify:

new Date(1751328000000).toLocaleString('en-US', {
  timeZone: 'Asia/Shanghai',
});

For storing timestamps in a database, prefer storing the numeric timestamp (or an ISO 8601 string in UTC). Avoid storing "local time" strings without a timezone offset — you will regret it.


Common conversions

Timestamp → ISO 8601

new Date(1751328000000).toISOString();
// "2026-07-01T00:00:00.000Z"

ISO 8601 → timestamp

Date.parse("2026-07-01T00:00:00.000Z");
// 1751328000000

Timestamp → human-readable

new Date(1751328000000).toLocaleString('en-US', {
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  timeZone: 'UTC',
});
// "Wednesday, July 1, 2026 at 12:00:00 AM"

Timestamp → date only

new Date(1751328000000).toISOString().slice(0, 10);
// "2026-07-01"

Edge cases

Leap seconds

Unix timestamps skip leap seconds. When a leap second is inserted, the timestamp counts 23:59:60 and then 23:59:60 again (same timestamp twice). Most systems ignore leap seconds entirely and treat the day as 86401 seconds long with no special handling. This means timestamps across leap-second boundaries are not perfectly precise — but for almost all applications, this does not matter.

Dates before 1970

Negative timestamps work. new Date(-1) is 1969-12-31T23:59:59.999Z. Most languages handle this correctly, but some older systems do not.

Year 2038 problem

A 32-bit signed integer overflows at 2^31 - 1 = 2,147,483,647 seconds, which is 2038-01-19 03:14:07 UTC. Systems still using 32-bit timestamps will break on that date. Modern systems use 64-bit integers and are safe until the year 292 billion.


Try it yourself

Open the free RuMystic Timestamp Converter:

  • Auto-detects seconds, milliseconds, microseconds, nanoseconds from the digit count.
  • Converts to local time, UTC, and any timezone you pick.
  • Bidirectional: type a date, get the timestamp.
  • Copy-paste friendly.
  • No upload — your input stays in the browser.
Time well spent.