Timestamp Converter
Convert between Unix timestamps (seconds/milliseconds) and ISO 8601 / JST / UTC. For log analysis, API debugging, and date verification during data migration.
| Unix (sec) | |
|---|---|
| Unix (ms) | |
| ISO 8601 (UTC) | |
| ISO 8601 (JST) | |
| JST (Japan Time) | |
| UTC | |
| RFC 2822 | |
| Day of week (JST) | |
| Relative time |
Copied
📖 Where people get stuck
Converts between Unix timestamps (seconds or milliseconds) and ISO 8601, JST and UTC. Whether a number is seconds or milliseconds is inferred from its length: 13 digits or more is treated as milliseconds, 10 digits as seconds. That is a rule of thumb which almost always holds in practice, not a specification. A timestamp carries neither a unit nor a time zone inside it, so the only thing that settles the question is the documentation of whatever produced the value.
| Case | What happens | What to do |
|---|---|---|
| The result lands in 1970, or fifty thousand years from now | This is the classic symptom of confusing seconds with milliseconds. Read a millisecond value as seconds and you land around the year 55000; read a second value as milliseconds and you land around 20 January 1970. The cause is that languages disagree on the default unit: Date.now() in JavaScript and System.currentTimeMillis() in Java are milliseconds, while time() in PHP, time.time() in Python and date +%s in a shell are seconds. It bites at every boundary where JSON crosses from one language to another. |
Counting digits is the fastest test. Since 9 September 2001, seconds are 10 digits and milliseconds are 13, both until 2286, so distinguishing those two is enough for the foreseeable future. On the design side, putting the unit in the field name causes the fewest accidents: name it expires_at_ms rather than expires_at and the consumer cannot misread it. Better still, pass an ISO 8601 string if you can — a human can read it, so this class of mistake gets caught in code review. |
| The same date string means different times in different places | A string without a time zone is interpreted at the implementation the way each implementation chooses. In JavaScript, 2024-01-01 (date only) is read as UTC while 2024-01-01T00:00:00 (with a time) is read as local — one character of difference, nine hours apart. A space-separated form like 2024-01-01 09:00:00 is outside both ISO 8601 and ECMAScript, so every browser makes up its own answer. With a UTC server and a JST laptop, this surfaces as code that works locally and is nine hours out in production. |
Never write a string without a time zone. Always append Z or +09:00: 2024-01-01T00:00:00Z names exactly one instant in every implementation. The operating rule is store in UTC and convert to local only for display. The same trap exists in database column types: MySQL TIMESTAMP values are converted using the session time zone on the way out, while DATETIME hands back the literal string you wrote. Move the server and change time_zone, and only the TIMESTAMP columns appear to shift, historical rows included. |
| A fixed offset breaks on daylight saving or a law change | An offset like +09:00 records the gap at one instant, not a place. JST has no daylight saving, so a purely domestic Japanese system rarely notices, but it falls apart the moment you have American or European users: New York moves between -05:00 and -04:00 twice a year, so a weekly Monday 9am meeting saved in March with -05:00 rings at 8am in April. Offsets change by legislation, too — Samoa crossed the date line in 2011, and that year simply had no 30 December. |
Store past events as instants (UTC) and future appointments as an IANA time zone name plus a local time. The two have different jobs: a log entry only needs to say when something happened, but an appointment is a promise about 9am where the person is, so unless you keep Asia/Tokyo or America/New_York as a region, every rule change moves the meeting. The time zone database (tzdata) is updated several times a year — a pinned container image keeps running the old rules, which is why refreshing base images matters for reasons beyond security. |
A Unix timestamp is not the number of seconds elapsed since 1970-01-01T00:00:00Z — it is a count that pretends leap seconds never happened, and as of 2026 it differs from true elapsed time by 27 seconds. Ordinary applications can ignore this, but if you order financial trades or reason about causality in a distributed system, that second matters: when a leap second is inserted, some systems emit the same timestamp twice, or step the clock backwards by one second. Google and AWS instead smear the adjustment across a whole day, which means their clocks sit up to half a second away from everyone else that day. Where uniqueness matters, do not use a timestamp as a primary key — pair it with a monotonically increasing id.
📖 How to Use
-
1
Enter a timestamp or datetime stringType a Unix timestamp (seconds or milliseconds) or a datetime string in ISO 8601 / RFC 2822 format. Seconds vs milliseconds are detected automatically by digit count.
-
2
Check the conversion resultsUnix seconds, milliseconds, ISO 8601 (UTC/JST), RFC 2822, day of week, and relative time are all shown together. Click any row to copy that value.
-
3
Adjust with the offset buttonsUse the -1 day / -1 h / +1 h / +1 day buttons to shift the timestamp and verify boundary values or adjacent log times.
❓ Frequently Asked Questions
How are seconds and milliseconds distinguished?
What is JST?
What is a Unix timestamp?
🐛 Found a bug or issue with this tool?
Free to use, no signup. Even just the steps to reproduce are helpful. Reports go directly to the operator and help us fix issues.
Thanks for your report!
Your report has been delivered to the operator and will be used to improve the tool.