Unix Timestamp Converter — Free HTML CSS JS Snippet

Unix Timestamp Converter · Dev · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Explicit seconds-vs-milliseconds unit toggle, eliminating the most common Unix timestamp conversion bug
Bidirectional conversion: edit the timestamp or the native datetime-local picker, both stay in sync
Six simultaneous derived formats: epoch seconds, epoch milliseconds, ISO 8601 UTC, RFC UTC string, local string, relative time
Human-readable relative time ("in 3 hours", "2 days ago") via the built-in Intl.RelativeTimeFormat API, no manual string logic
Live "current time" banner updating every second via setInterval
One-click "Use current time" button populates both input fields instantly
Inline validation for non-numeric timestamps and out-of-range dates
Uses the browser's native datetime-local input, so date entry respects the user's OS locale and format preferences

About this UI Snippet

Unix Timestamp Converter — Bidirectional Epoch-to-Date Conversion with Relative Time via Intl.RelativeTimeFormat

Screenshot of the Unix Timestamp Converter snippet rendered live

A Unix timestamp counts seconds (or, in many JavaScript APIs, milliseconds) since 00:00:00 UTC on January 1, 1970 — the "epoch." It's the backbone of how most systems store and compare points in time internally, but it's meaningless to read at a glance, which is why converting a log line's or a JWT's exp claim's timestamp into an actual date is one of the most common small tasks a developer does in a day.

Seconds versus milliseconds — the single most common bug

JavaScript's own Date object and Date.now() work in milliseconds, but the Unix timestamp standard (and most backend languages' native epoch functions) work in seconds. Mixing the two up produces a date either 1970-ish (treating a seconds value as milliseconds gives a date near the epoch) or thousands of years in the future (treating a milliseconds value as seconds). This converter makes the unit an explicit, visible choice via the unit-select dropdown rather than guessing — fromTimestamp() multiplies by 1000 only when seconds is selected, so the ambiguity that causes this bug in real code is impossible to hide here.

Two-way binding without a feedback loop

The timestamp field and the browser-native datetime-local input both update the *other* field on input, which risks an infinite update loop if implemented naively (input A changes, updates B, which fires B's input handler, which updates A, forever). This snippet avoids that by keeping each direction as a fully separate function — fromTimestamp() parses the numeric field and writes into dateInput.value via imperative assignment (which does not fire a synthetic input event in real browsers), and fromDate() does the reverse. Each field's own listener only ever triggers a write to the *other* field, never back to itself, which is what keeps the pair in sync without recursion.

Relative time via the built-in Intl API

Rather than hand-writing "3 hours ago" / "in 2 days" string logic — which inevitably accumulates edge cases around pluralization and unit boundaries — relativeTime() uses Intl.RelativeTimeFormat, a standard built into every modern browser specifically for this. It walks a list of unit thresholds from year down to second, picks the largest unit where the elapsed time is at least one full unit, and hands the rounded value to rtf.format(value, unit), which handles the "ago" vs. "in" phrasing, pluralization, and locale formatting automatically based on the sign of value.

Six simultaneous output formats

Once a valid date is established from either input, renderResults() derives six representations from the same underlying Date object: raw seconds, raw milliseconds, toISOString() (always UTC, the format most APIs expect in request bodies), toUTCString() (the RFC 7231 format used in HTTP headers like Date and Expires), toString() (formatted in the browser's local timezone, useful for sanity-checking what a timestamp means to the person actually looking at the page), and the Intl.RelativeTimeFormat relative string. Seeing all six side by side from one input is deliberately the point — it eliminates having to convert a value five separate times to check it against five different systems' expected formats.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Give this snippet's JavaScript to an AI assistant like Claude and ask it to explain exactly why the two-way binding between the timestamp field and the datetime-local field doesn't create an infinite update loop — the answer hinges on how programmatic .value assignment differs from user-driven input events, and it's a pattern worth understanding for any bidirectional form sync. It's also easy to extend: ask for a timezone-selector dropdown so the "Local string" output can show a timezone other than the browser's own, a batch mode that converts a pasted list of timestamps at once, or a countdown display for a future timestamp.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a bidirectional Unix timestamp converter in plain HTML, CSS, and JavaScript, no libraries.

Requirements:
- A text input for a numeric Unix timestamp, with a dropdown to explicitly choose whether it represents seconds or milliseconds since the epoch (do not guess the unit from the magnitude of the number).
- A native <input type="datetime-local"> field that stays in sync with the timestamp field in both directions: editing the timestamp updates the date picker, and editing the date picker updates the timestamp, without creating an infinite update loop between the two.
- Derive and display simultaneously from the current value: the epoch value in both seconds and milliseconds, an ISO 8601 UTC string, an RFC-style UTC string (like the HTTP Date header format), the browser's local-timezone string representation, and a human-readable relative time string (e.g. "3 hours ago" or "in 2 days") generated using the built-in Intl.RelativeTimeFormat API rather than hand-written string logic.
- Add a "Use current time" button that populates both the timestamp and date fields with the current moment.
- Show a live banner with the current Unix timestamp in seconds, updating once per second.
- Validate numeric input and out-of-range dates with a clear inline error message rather than displaying "Invalid Date" or NaN anywhere in the UI.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste a Unix timestampType or paste a numeric epoch value into the timestamp field, and choose whether it's in seconds or milliseconds using the dropdown.
  2. 2
    Or pick a date and time directlyUse the datetime-local field to select a date/time using your browser's native picker — the timestamp field updates automatically to match.
  3. 3
    Click "Use current time"Instantly loads the current moment into both fields as a quick starting point or sanity check.
  4. 4
    Read all six derived formatsSeconds, milliseconds, ISO 8601 UTC, RFC UTC string, local time string, and a human relative phrase like "3 hours ago" all update together.
  5. 5
    Switch the unit dropdownToggling between seconds and milliseconds reinterprets whatever numeric value is currently in the timestamp field.
  6. 6
    Watch the live "Now" tickerThe banner at the top shows the current Unix timestamp in seconds, updating every second, as a quick reference for "what time is it right now" in epoch form.

Real-world uses

Common Use Cases

Debugging log timestamps and JWT expiry claims
Paste an epoch value straight from a server log line or a decoded JWT's exp/iat claim to instantly see what date and time it actually represents.
Constructing API request payloads
Pick a target date and time with the native picker, then copy the ISO 8601 or epoch-seconds output directly into an API request body that expects a specific timestamp format.
Scheduling and cron job verification
Confirm that a scheduled job's stored epoch timestamp lines up with the intended local wall-clock time before it fires in production.
Teaching how Unix time and Intl.RelativeTimeFormat work
Demonstrate the seconds/milliseconds pitfall live by flipping the unit dropdown on the same numeric value and watching the resulting date jump by orders of magnitude.
QA verification of date-sensitive features
Cross-check a database's stored epoch value against the UI's displayed relative time ("3 days ago") to catch timezone or unit-conversion bugs before release.
Related: Regex Tester & Match Visualizer
See the Regex Tester & Match Visualizer for a related dev pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

Both count elapsed time since the Unix epoch (00:00:00 UTC, January 1 1970), but seconds-based timestamps are the traditional Unix/POSIX standard used by most backend languages, while JavaScript's Date.now() and new Date() work in milliseconds. Treating a seconds value as milliseconds (or vice versa) produces a date off by a factor of 1000, which is why this tool makes the unit an explicit dropdown rather than guessing.

Intl.RelativeTimeFormat is a standard, built-in browser API specifically designed for this: it correctly handles singular/plural phrasing, locale-appropriate wording, and the "ago" versus "in" distinction based on whether the value is negative or positive, without any hand-written string-concatenation logic that would need constant edge-case patching.

Each input field has its own event listener that only writes into the other field, never back into itself. Programmatically setting an input's .value property in JavaScript does not fire that same element's own input event, so there's no risk of the two fields triggering each other repeatedly.

toISOString() and toUTCString() always output UTC regardless of the browser's configured timezone — this is required for ISO 8601 and is the convention for the UTCString/RFC 7231 HTTP date format. The "Local string" row uses toString(), which formats the same underlying moment in the browser's own local timezone, useful for sanity-checking what a timestamp means to the person actually viewing the page.

Extremely large or invalid numeric values that JavaScript's Date constructor cannot represent produce an "Invalid Date" internally, which the tool detects with isNaN(date.getTime()) and reports as an out-of-range error instead of silently displaying garbage output.