StringToolsStringTools

Time Format Converter

Convert between 24-hour and 12-hour time formats instantly. Supports military time, bulk conversion, and auto-detection.

Mitul MandankaFounder, Progragon Technolabs · 15+ years building software
Updated June 20268 min read
Input
Auto-detect
Converted
Result will appear here...
Common Time Reference
00:0012:00 AM
01:001:00 AM
02:002:00 AM
03:003:00 AM
04:004:00 AM
05:005:00 AM
06:006:00 AM
07:007:00 AM
08:008:00 AM
09:009:00 AM
10:0010:00 AM
11:0011:00 AM
12:0012:00 PM
13:001:00 PM
14:002:00 PM
15:003:00 PM
16:004:00 PM
17:005:00 PM
18:006:00 PM
19:007:00 PM
20:008:00 PM
21:009:00 PM
22:0010:00 PM
23:0011:00 PM

TL;DR

The converter above handles clock time — 24-hour (military) to 12-hour AM/PM and back. The guide below covers the harder problem most developers actually land here for: machine time. A Unix timestamp is just a count of seconds since 1970-01-01T00:00:00Z. The single most common bug is mixing up seconds and milliseconds — a 10-digit number is seconds, a 13-digit number is milliseconds. Always store and transmit time in UTC; convert to local time only at the moment you display it.

Every common timestamp format, side by side

The same instant in time — Sunday, 14 June 2026 at 09:30:00 UTC — written in each of the formats you will run into across logs, APIs, databases, and email headers. If a value will not parse, this table is usually enough to spot which format it actually is.

FormatExampleNotes
Epoch seconds178142940010 digits today. The Unix default. No timezone — always UTC. Used by date +%s, most C/Go/Rust APIs.
Epoch milliseconds178142940000013 digits today. What JavaScript's Date.now() and Java's System.currentTimeMillis() return. The classic 1000x bug.
ISO 8601 (UTC)2026-06-14T09:30:00ZThe Z means Zulu / UTC (zero offset). Sorts correctly as plain text. The format to default to.
ISO 8601 (offset)2026-06-14T05:30:00-04:00Same instant in US Eastern (EDT). The -04:00 is the offset, not a timezone name. DST changes this offset twice a year.
RFC 2822Sun, 14 Jun 2026 09:30:00 +0000The email and HTTP header format (a.k.a. RFC 5322). Seen in Date: headers and RSS pubDate.
SQL datetime2026-06-14 09:30:00ISO with a space instead of T and no offset. TIMESTAMP vs DATETIME in MySQL behave differently around timezones.
HTTP dateSun, 14 Jun 2026 09:30:00 GMTUsed in Expires, Last-Modified, and Date response headers. Always GMT/UTC by spec.

Seconds vs milliseconds: the 1000x bug

This is the timestamp bug everyone hits at least once. A Unix timestamp can be a count of seconds or milliseconds since the epoch, and the two differ by a factor of 1000. Feed one where the other is expected and your date lands either 50 years in the future or back in 1970.

The quick check is digit count. As of 2026, a seconds timestamp is 10 digits; a milliseconds timestamp is 13 digits:

1781429400       -> seconds   (10 digits)  -> 2026-06-14
1781429400000    -> millis     (13 digits)  -> 2026-06-14

// Reading millis as seconds:  year ~58421  (way in the future)
// Reading seconds as millis:  1970-01-21   (three weeks after epoch)

The trap is language defaults. JavaScript's Date constructor and Date.now() work in milliseconds, so new Date(1781515800) (passing seconds) gives you 21 January 1970. Most other ecosystems — Unix date, Python's time.time() (a float of seconds), Go, Ruby, PostgreSQL to_timestamp() — default to seconds. Whenever a value crosses that boundary, multiply or divide by 1000 explicitly:

// seconds (from an API) -> JS Date
new Date(epochSeconds * 1000)

// JS millis -> seconds (to send to a seconds-based API)
Math.floor(Date.now() / 1000)

UTC, local time, offsets, and DST — what actually goes wrong

A Unix timestamp has no timezone

An epoch number is an absolute instant — the same all over the planet. There is no "timestamp in EST." Timezone only enters the picture when you render that instant as a human-readable date. Store the instant in UTC, attach the user's timezone separately, and apply it at display time. The golden rule: store UTC, display local.

An offset is not a timezone

-04:00 is an offset — a fixed number of hours from UTC at one moment. America/New_York is a timezone — a set of rules that says when the offset is -05:00 (winter, EST) versus -04:00(summer, EDT). Storing only an offset loses the DST rules, so you cannot correctly compute a future date. If you need to schedule something for "9 AM local next March," store the IANA timezone name, not the offset.

DST creates times that do not exist (and times that happen twice)

On the US spring-forward day, clocks jump from 02:00 straight to 03:00 — so 02:30local time simply never happens. On the fall-back day, 01:30 occurs twice. Code that assumes "every day has 24 hours" or "every local time exists exactly once" will throw or silently pick the wrong instant. This is why you should do date math in UTC and only convert to local for display.

Why ISO 8601 is the safe default

2026-06-14T09:30:00Z is unambiguous, sorts correctly as plain text (lexical order equals chronological order), and is parsed identically everywhere — JavaScript's Date.parse, Python's datetime.fromisoformat, Postgres, and Java's Instant.parse all understand it. Avoid locale formats like 06/14/2026: is that 14 June or the 6th of the 14th month? ISO ends that argument.

The Year 2038 problem (Y2K38)

Older systems store the epoch in a signed 32-bit integer (time_t). The largest value that fits is 2,147,483,647 seconds, which is reached at 03:14:07 UTC on 19 January 2038. One second later the counter overflows and wraps to a negative number, putting affected systems back in December 1901.

2147483647  -> 2038-01-19T03:14:07Z   (last valid 32-bit second)
2147483648  -> overflows to negative  -> 1901-12-13

Modern 64-bit systems use a 64-bit time_t and are safe for roughly 292 billion years, so most current Linux, macOS, and database installs are fine. The risk lives in long-lived embedded devices, legacy C code, some 32-bit binaries, and any data format that froze a 32-bit field. It is the direct sequel to Y2K — and unlike Y2K, the deadline is fixed and known.

Common timestamp questions, answered

Is my Unix timestamp in seconds or milliseconds?

Count the digits. For dates around now (2026), a 10-digit number is seconds and a 13-digit number is milliseconds. If converting the value gives you a date far in the future, you read seconds as milliseconds — divide by 1000. If you land in January 1970, you read milliseconds as seconds — multiply by 1000.

Why does my JavaScript Date show 1970 from a Unix timestamp?

JavaScript's Date constructor expects milliseconds, but most APIs return seconds. Passing seconds (a 10-digit number) lands you about three weeks after the epoch, in January 1970. Multiply by 1000 first: new Date(epochSeconds * 1000).

What does the Z in 2026-06-14T09:30:00Z mean?

The Z stands for "Zulu time," which is UTC — an offset of zero. It is equivalent to writing +00:00. A timestamp ending in Z is in UTC; one ending in something like -04:00 is shifted that many hours from UTC.

Should I store dates in UTC or local time?

Store UTC, display local. Keep the instant in UTC (as an epoch number or an ISO string ending in Z) and convert to the user's timezone only when you render it. The one exception: for future events tied to a wall-clock time ("9 AM next March"), also store the IANA timezone name like America/New_York so daylight saving is applied correctly.

What exactly is the Year 2038 problem?

Systems that store the epoch in a signed 32-bit integer overflow at 03:14:07 UTC on 19 January 2038, wrapping to a negative number and jumping back to 1901. 64-bit systems are unaffected. The lingering risk is in legacy 32-bit software, embedded devices, and fixed-width data formats.

Does this converter handle Unix timestamps or timezones?

No — the tool above converts clock time between 24-hour and 12-hour AM/PM formats and runs entirely in your browser. It does not parse epoch timestamps or apply timezone math. This guide covers those concepts so you can reason about the format before you reach for code or a dedicated epoch converter.