I built a small Unix timestamp converter — paste in seconds or milliseconds, get a date back, or go the other way. Simple enough that I figured the only real work would be the date math. Then I went to add "tell the user when they typed garbage" and ran straight into a JavaScript gotcha that's been quietly living in more codebases than anyone wants to admit.
The unit dropdown is secretly a multiplier, not a branch
The converter has a unit selector next to the input — "Seconds" or "Milliseconds." The tempting way to wire that up is an if/else: if seconds, do this math; if milliseconds, do that math. That's not what's in the actual component. The <a-select> options are bound directly to the numbers 1 and 1000, and those numbers get used as literal arithmetic operands everywhere downstream:
const unixToNoraml_getOutput = () => {
let unix = data.unixToNoraml.unix;
let unit = data.unixToNoraml.unit; // 1 or 1000
let output = new Date(Math.floor((unix * 1000) / unit));
data.unixToNoraml.output = output;
};
If unit is 1 (seconds), that's unix * 1000 / 1 — converts seconds to the milliseconds Date wants. If unit is 1000 (milliseconds), it's unix * 1000 / 1000, which cancels out and leaves the value untouched, because it was already in milliseconds. Same one-liner handles both cases with no conditional at all.
The reverse direction does the same trick in reverse — compute the answer in seconds, then multiply by the unit to get either seconds or milliseconds back out:
const normalToUnixOutputFormat = computed(() => {
if (!data.normalToUnix.output) return "";
return data.normalToUnix.output * data.normalToUnix.unit;
});
It's a small thing, but reusing the dropdown's raw value as a multiplier instead of introducing a "seconds" | "milliseconds" enum saved a branch in four separate places in the component.
The validation check that doesn't actually validate anything
Here's the one that got me. When you type a date string into the "normal time" field and hit convert, the code tries to reject bad input before doing math on it:
if (new Date(normal) === "Invalid Date") {
return Swal.fire({
title: t("timestamp.error"),
icon: "warning",
confirmButtonColor: "#1890ff",
});
}
let output = new Date(normal).getTime() / 1000;
new Date("not a real date") doesn't throw and doesn't return the string "Invalid Date" — it returns an actual Date object whose internal time value is NaN. Calling .toString() on that object prints "Invalid Date", but the object itself is never, ever === to a string, no matter what garbage you feed it. So that guard clause is dead code. It will never fire, for any input, ever.
What actually keeps the tool from displaying literal "NaN" to the user is something else entirely, three lines away in a computed property:
const normalToUnixOutputFormat = computed(() => {
if (!data.normalToUnix.output) return "";
return data.normalToUnix.output * data.normalToUnix.unit;
});
NaN / 1000 is still NaN, and !NaN evaluates to true in JavaScript — so the falsy check blanks the output field instead of the intended validation ever running. The tool behaves correctly, but by accident: the real safety net is a coincidental side effect of how NaN interacts with !, not the Swal.fire() warning dialog that was written to handle exactly this case. The correct check would be isNaN(new Date(normal).getTime()), but that's not what's in the file.
The live clock ticks in your local time, not UTC
The page also has a running "current timestamp" display that updates once a second, with pause/continue buttons:
const init_clock = () => {
if (data.timer) return;
data.timer = setInterval(() => {
let now = new Date();
data.currentUnix = Math.round(now.getTime() / 1000);
data.currentLocalString = DateTime.fromSeconds(data.currentUnix).toFormat(
"yyyy/MM/dd HH:mm:ss",
);
}, 1000);
};
const pause_clock = () => {
clearInterval(data.timer);
data.timer = null;
};
Two things worth calling out. First, setInterval(..., 1000) doesn't guarantee a tick every exact second — it just re-reads Date.now() and rounds each time it fires, so under heavy main-thread load a tick can land late; the displayed number just catches up rather than drifting permanently. Second, DateTime.fromSeconds() from Luxon defaults to the local system time zone when you don't pass one — so the human-readable clock next to the raw Unix number is your machine's local time, not UTC, even though a Unix timestamp is by definition timezone-independent. There's no UTC toggle for it. If you're in Tokyo and I'm in Berlin, we see the same integer but a different clock face next to it.
Limitations, honestly
- No digit-count auto-detection. I assumed a paste-in converter like this would sniff "10 digits, must be seconds" vs "13 digits, must be milliseconds." It doesn't — the unit is a manual dropdown. Paste a 13-digit millisecond value while "Seconds" is still selected and you silently get a date several thousand years in the future. No warning, no clamp.
- Everything renders in local time. The seconds-since-epoch value is timezone-agnostic by definition, but every human-readable output on the page — the live clock, the converted date — is displayed in whatever timezone the browser is set to, with no UTC option. If you're debugging a server log recorded in UTC, you have to do the offset math yourself.
-
The "type a date manually" field parses whatever
new Date(string)accepts, which is a browser-implementation detail, not a fully spec'd format. It works fine for theYYYY/MM/DD HH:MM:SSshape the placeholder suggests, but it's not the same guarantee you'd get from an explicit parser. -
The Invalid Date check discussed above never runs. It's harmless here because
NaN's falsiness happens to save it, but it means the warning dialog telling you "please enter a valid time" is unreachable code.
I turned the cleaned-up version into a small free tool: Unix Timestamp Converter. No sign-up, works entirely in the browser.
Available in other languages
- Unix時間戳轉換工具 — 繁體中文
- Unix时间戳转换器 — 简体中文
- Unix Timestamp Converter — English
- Unixタイムスタンプ変換ツール — 日本語
- Unix 타임스탬프 변환기 — 한국어
- Outil de Conversion de Timestamp Unix — Français
- Конвертер Unix Timestamp — Русский
- Unix-Zeitstempel-Konverter — Deutsch
- Alat Konversi Unix Timestamp — Bahasa Indonesia
- Conversor de Unix Timestamp — Español
- Công cụ chuyển đổi Unix Timestamp — Tiếng Việt
- เครื่องมือแปลง Unix Timestamp — ไทย
- Konwerter znacznika czasu Unix — Polski
- Unix Timestamp Dönüştürme Aracı — Türkçe
- Strumento di conversione Unix Timestamp — Italiano
- Conversor de Unix Timestamp — Português
- Unix Timestamp Conversie Tool — Nederlands
- Інструмент конвертації Unix Timestamp — Українська
Top comments (0)