DEV Community

tommy
tommy

Posted on

I Built a Unix Timestamp Converter and Stepped on 3 JavaScript Date API Landmines

An API response returns 1709654400.

Can you tell what date that is at a glance? I couldn't. Every time, I'd google "Unix Timestamp converter" and paste it into some online tool. That tiny friction adds up, so I decided to build my own converter.

Try it out: timestamp.puremark.app — zero-click timestamp conversion, right in your browser.

I got it working, but not before stepping on 3 landmines in JavaScript's Date API.

Landmine 1: new Date(1709654400) Returns 1970

I started confidently. Just pass the timestamp to new Date().

const date = new Date(1709654400);
console.log(date.toISOString());
// => "1970-01-20T21:34:14.400Z"
Enter fullscreen mode Exit fullscreen mode
  1. Way off.

The cause was simple: JavaScript's Date expects milliseconds, but Unix timestamps are in seconds. You need to multiply by 1000.

const date = new Date(1709654400 * 1000);
console.log(date.toISOString());
// => "2024-03-05T00:00:00.000Z"
Enter fullscreen mode Exit fullscreen mode

But should users have to think about whether they're entering seconds or milliseconds? No. I implemented auto-detection by digit count: 10 digits = seconds, 13 digits = milliseconds.

function toMillis(input) {
  if (/^\d{10}$/.test(input)) return Number(input) * 1000;
  if (/^\d{13}$/.test(input)) return Number(input);
  return NaN;
}
Enter fullscreen mode Exit fullscreen mode

Three lines. But without them, every input becomes a guessing game.

Landmine 2: Hyphens and Slashes Parse Differently

Next, I added date-string-to-timestamp conversion. Type 2024-03-05, get the Unix timestamp. Should be simple.

console.log(new Date('2024-03-05').toISOString());
// => "2024-03-05T00:00:00.000Z" (UTC)

console.log(new Date('2024/03/05').toISOString());
// => "2024-03-04T15:00:00.000Z" (JST midnight = UTC previous day)
Enter fullscreen mode Exit fullscreen mode

Same date, different separators, completely different results. Hyphens get parsed as UTC (ISO 8601), slashes get parsed as local time (implementation-dependent).

MDN says it clearly:

Parsing date strings with the Date constructor is strongly discouraged due to browser differences and inconsistencies.

The lesson: never trust new Date() with non-ISO-8601 strings.

Landmine 3: The Timezone Display Maze

Once conversion worked, I wanted a timezone comparison table — "What time is this in Tokyo? New York? Berlin?"

My first attempt was getTimezoneOffset().

const offset = new Date().getTimezoneOffset();
console.log(offset); // JST: -540
Enter fullscreen mode Exit fullscreen mode

The sign is inverted. JST is UTC+9, but getTimezoneOffset() returns -540 minutes (= -9 hours). Plus, it only returns the user's local timezone — you can't get arbitrary timezones with it.

The solution: Intl.DateTimeFormat.

const date = new Date('2024-03-05T10:00:00Z');
date.toLocaleString('en-US', {
  timeZone: 'Asia/Tokyo',
  hour12: false,
  year: 'numeric', month: '2-digit', day: '2-digit',
  hour: '2-digit', minute: '2-digit', second: '2-digit'
});
// => "03/05/2024, 19:00:00"
Enter fullscreen mode Exit fullscreen mode

Just pass an IANA timezone identifier to the timeZone option. No external libraries needed. I implemented a 10-timezone comparison table covering UTC, JST, EST, PST, CET, GMT, IST, CST, AEST, and BRT.

See it in action: timestamp.puremark.app shows your timestamp across 10 cities at a glance. Each row has a copy button for pasting into Slack or Jira.

Before / After

Before After
Checking timestamps Google → copy-paste to some online tool Just open a browser tab. Auto-reads from clipboard
Seconds vs milliseconds Count digits manually Auto-detected. Don't even think about it
Date string parsing Trust new Date(), get bitten by browser differences Know that non-ISO-8601 is unreliable
Timezones Confused by getTimezoneOffset() sign Intl.DateTimeFormat with 10-city display

All three landmines are "obvious once you know" but can cost you hours if you don't. Hope this article saves you that time.

Timestamp converter → timestamp.puremark.app


References

Top comments (0)