UUID Studio

Timestamp Converter

Unix ↔ ISO ↔ local time.

  • 🔒 No data stored or uploaded
  • ⚡ 100% client-side
  • 🆓 Free, no account

Need more than one tool at a time? Open the full Workbench - or press Ctrl+K to jump to any tool.

Create or edit JSON here (syntax colors), then format, validate, or convert - same as MongoDB $binary UUID blobs on the Convert tab once detected.

New document

About Timestamp Converter

A Unix timestamp counts seconds since 1970-01-01T00:00:00Z. It has no timezone - it is an absolute instant - which is precisely why it is the right thing to store and transmit, and why so many bugs come from code that treats it as though it had one.

The first thing to check whenever a date is wildly wrong is the unit. Unix time is in seconds, JavaScript's Date.now() and Java's System.currentTimeMillis() are in milliseconds, and Python's time.time() returns seconds as a float. Passing milliseconds where seconds are expected lands you around the year 56000; passing seconds where milliseconds are expected lands you in January 1970. A current timestamp in seconds is 10 digits; in milliseconds it is 13.

ISO 8601 is the format to use whenever a human or another system reads the value, but only with an explicit offset. 2026-08-31T14:30:00Z is unambiguous; 2026-08-31T14:30:00 is not, and different parsers disagree about it - JavaScript historically treated a bare date-time as local but a date-only string as UTC, which is a genuinely surprising inconsistency.

Two overflow dates are worth knowing. A signed 32-bit timestamp overflows on 19 January 2038, which still matters for embedded systems, older C code and any database column defined as a 4-byte integer. MySQL's TIMESTAMP type has the same limit, while DATETIME does not. The 2038 problem is the 2000 problem with a longer fuse.

Conversion runs in your browser using your local timezone for display, and nothing is transmitted.

How to use the Timestamp Converter

  1. Paste a timestamp or a date string - the tool detects seconds versus milliseconds by magnitude.
  2. Read the value in UTC and in your local timezone; the difference is where most 'off by some hours' bugs live.
  3. Check the digit count if the result looks absurd: 10 digits is seconds, 13 is milliseconds.
  4. Copy the format you need, preferring ISO 8601 with an explicit offset for anything another system will parse.

Examples

  • Unix seconds
    1700000000

Timestamp Converter in code

The same operation this tool performs, in the languages you are most likely to need it.

JavaScript
// Date takes MILLISECONDS - the most common conversion bug
new Date(1756651800 * 1000).toISOString();   // "2026-08-31T14:30:00.000Z"
Math.floor(Date.now() / 1000);               // current Unix seconds

// Always parse with an explicit offset
new Date("2026-08-31T14:30:00Z");        // unambiguous
new Date("2026-08-31T14:30:00");         // local time (implementation-dependent)
new Date("2026-08-31");                  // UTC midnight - inconsistent with the above!

// Formatting in a specific zone without a library
new Intl.DateTimeFormat("en-GB", {
  timeZone: "Europe/London",
  dateStyle: "medium", timeStyle: "long",
}).format(new Date());

// Temporal, where available, removes most of this sharp edge
// Temporal.Instant.fromEpochSeconds(1756651800)
//   .toZonedDateTimeISO("Europe/London");
Python
from datetime import datetime, timezone

# Always pass tz - utcnow() and utcfromtimestamp() return NAIVE
# datetimes that claim no timezone, and are deprecated in 3.12+.
datetime.fromtimestamp(1756651800, tz=timezone.utc)
datetime.now(timezone.utc).timestamp()

# Parsing ISO 8601 (3.11+ handles Z and offsets properly)
datetime.fromisoformat("2026-08-31T14:30:00Z")

# A specific zone
import zoneinfo
datetime.fromtimestamp(1756651800, tz=zoneinfo.ZoneInfo("Europe/London"))

# Naive vs aware is the Python-specific trap: comparing or
# subtracting a naive and an aware datetime raises TypeError.
SQL
-- PostgreSQL: use timestamptz, essentially always
SELECT to_timestamp(1756651800);                    -- epoch -> timestamptz
SELECT EXTRACT(EPOCH FROM now())::bigint;           -- -> epoch seconds
SELECT now() AT TIME ZONE 'Europe/London';          -- render in a zone

-- timestamp (without time zone) stores wall-clock text with no offset,
-- so the same column means different instants for different clients.

-- MySQL: TIMESTAMP is 4 bytes and dies in 2038; DATETIME is 8 and does not
SELECT FROM_UNIXTIME(1756651800);
SELECT UNIX_TIMESTAMP(NOW());

-- SQLite has no date type at all - store INTEGER epoch seconds
SELECT datetime(1756651800, 'unixepoch');
Command line
# Now, in epoch seconds
date +%s

# Epoch -> human (GNU / Linux)
date -d @1756651800
date -u -d @1756651800 '+%Y-%m-%dT%H:%M:%SZ'

# macOS / BSD uses -r instead
date -r 1756651800

# Human -> epoch
date -d '2026-08-31 14:30:00 UTC' +%s

# Milliseconds (13 digits) need dividing first
date -d @$((1756651800000 / 1000))

When you need this

  • Turning a timestamp from a log line or database row into a readable date.
  • Working out whether a token's exp claim is in the past.
  • Checking whether a value is in seconds or milliseconds by its magnitude.
  • Converting between UTC and a specific timezone to explain an off-by-hours bug.
  • Producing an epoch value for a test fixture or an API query parameter.

Common problems and what causes them

Seconds and milliseconds mixed up
A current timestamp is 10 digits in seconds and 13 in milliseconds. Passing seconds to JavaScript's Date gives a date in January 1970; passing milliseconds where seconds are expected gives roughly the year 56000. Check the digit count first, always.
Parsing an ISO string with no offset
2026-08-31T14:30:00 has no timezone, and parsers disagree: JavaScript treats a bare date-time as local but a date-only string as UTC. Always include Z or an explicit offset in anything you transmit.
Python's naive versus aware datetimes
datetime.utcnow() returns a naive datetime that does not know it is UTC, and comparing or subtracting it against an aware one raises TypeError. Use datetime.now(timezone.utc) - utcnow() is deprecated from 3.12.
The 2038 problem
A signed 32-bit timestamp overflows on 19 January 2038. It still affects embedded systems, older C code, and MySQL's TIMESTAMP type (4 bytes) as opposed to DATETIME (8 bytes). Use 64-bit types now.
Storing local time instead of an instant
PostgreSQL's timestamp without time zone stores wall-clock text, so the same value means different instants for clients in different zones. Use timestamptz, store UTC, and convert only for display.
Daylight saving transitions
Local times in the skipped hour do not exist and times in the repeated hour are ambiguous. Adding 24 hours to a local time is not the same as adding one day. Do arithmetic on instants, or use a library with proper zone rules.
Leap seconds and the assumption of 86,400
Unix time deliberately ignores leap seconds, so it is not a true count of elapsed SI seconds. For ordinary application work this is a feature; for precise interval measurement use a monotonic clock instead.

FAQ

Is my timestamp in seconds or milliseconds?
Count the digits. A current timestamp is 10 digits in seconds and 13 in milliseconds. If a converted date lands in 1970 you passed seconds where milliseconds were wanted; if it lands tens of thousands of years out, the reverse.
Does a Unix timestamp have a timezone?
No - it is an absolute instant, seconds since the UTC epoch. Timezones only enter when you format it for display. That property is exactly why it is the right thing to store.
What is the 2038 problem?
A signed 32-bit integer holding seconds since 1970 overflows on 19 January 2038 and wraps to 1901. It affects legacy C code, embedded systems and MySQL's 4-byte TIMESTAMP type. DATETIME and 64-bit integers are unaffected.
Why is my date off by a few hours?
Something converted between UTC and local time when it should not have, or did not when it should. Check what the storage type means: PostgreSQL's timestamptz stores an instant, timestamp stores wall-clock text with no offset.
Which format should an API use for dates?
ISO 8601 with an explicit offset - 2026-08-31T14:30:00Z. It is unambiguous, sorts lexicographically, and is readable in a log. Epoch integers are also fine and compact; what causes problems is a format with no offset.
Should I store UTC or local time?
Store the instant in UTC and convert for display. The exception is a future local appointment - a 09:00 meeting stays at 09:00 even if the zone's offset rules change - where you should store the local time plus the zone identifier.

Related reading