๐ข Unix Timestamp Converter
Convert between Unix epoch timestamps (seconds or milliseconds) and human-readable dates.
What Your Codebase Gets Wrong About Unix Timestamps (And Why It Still Runs)
Somewhere in a production database right now, there is a column storing Unix timestamps as strings. Elsewhere, a backend is accidentally treating milliseconds as seconds and generating dates in 1970. Both bugs are live. Both applications are shipping features. This is not a horror story โ it is just how timestamp confusion actually plays out in the real world. The codebase survives because the wrong dates appear in edge cases, not on the homepage.
Unix timestamps deserve a closer look than most developers give them, because the format is deceptively simple and the failure modes are deceptively subtle.
The Epoch Is Not What You Think It Is
The Unix epoch โ midnight January 1, 1970 UTC โ is often described as "when Unix time began." That phrasing carries a slight myth: time did not begin then, and Unix itself did not begin exactly then either. The epoch is simply a convention, an arbitrary starting point chosen by early Unix developers so that time could be represented as a single signed integer counting elapsed seconds. The specific date was picked partly because it made arithmetic clean on the hardware of the era. There was no grand ceremony. A committee did not deliberate over 1970-01-01 versus some other anchor. It was pragmatic and a little arbitrary, just like most of the decisions that now underpin global software infrastructure.
What matters practically is that the epoch is fixed and universal. Every system that correctly implements Unix time agrees on the same zero point. January 1, 1970 at exactly 00:00:00 UTC equals zero. Every second after that increments the counter by one. This uniformity is the timestamp's core value: a single integer that means the same thing in Tokyo, Toronto, and Tbilisi, without any timezone metadata attached.
Seconds vs. Milliseconds: The Bug That Hides in Plain Sight
The single most common Unix timestamp mistake is not timezone confusion, not leap year handling, not daylight saving time. It is the seconds-versus-milliseconds mismatch. JavaScript's Date.now() returns milliseconds. Python's time.time() returns seconds (as a float). Go's time.Unix() takes seconds as its first argument and nanoseconds as its second. If you pass a JavaScript timestamp directly to a Python function expecting seconds, you get a date in the year 33658. If you pass a Python timestamp to JavaScript's new Date() without multiplying by 1000, you get a date in early January 1970.
The frustrating part is that both bugs are completely silent. There is no exception, no NaN, no out-of-range error. The code runs perfectly and produces a date โ just the wrong century. In practice, this bug is caught only when someone looks at the rendered date and notices something is off. Automated tests rarely catch it because the test itself often makes the same assumption as the code it is testing.
A useful heuristic for auto-detection: any integer with 13 or more digits is almost certainly a millisecond timestamp for a date in the 21st century. A 10-digit integer is almost certainly a second timestamp in the same range. Timestamps for dates in year 2001 through roughly 2038 fall neatly into these ranges. Before 2001, 10-digit second timestamps start with a 9 and remain 10 digits. After 2286, millisecond timestamps exceed 10 trillion and push past 13 digits. For practical date-handling in contemporary applications, the 13-digit rule is reliable.
The 2038 Problem Is Real but Probably Not Your Problem
The Year 2038 problem gets brought up with a mixture of genuine concern and performative alarm. On January 19, 2038, at 03:14:07 UTC, a 32-bit signed integer storing Unix seconds will overflow and roll over to a large negative number, representing December 13, 1901. Systems still using 32-bit signed integers for timestamps โ embedded devices, older Linux kernels, legacy C code โ will behave unpredictably.
The myth is that this is a universal crisis waiting to happen. The reality is that most modern software already uses 64-bit integers for time, which gives you enough range to represent dates until roughly the year 292 billion. 64-bit timestamps do not overflow in any practical sense. Linux switched to 64-bit time on 32-bit systems years ago. Python, JavaScript, and Go all use 64-bit representations internally. The actual risk in 2038 is concentrated in specific legacy systems: industrial controllers, older embedded firmware, database schemas that deliberately used INT(10) as their timestamp column type, and applications built on old 32-bit POSIX assumptions.
If you are writing new code today and you are not specifically targeting embedded systems with constrained integer widths, you are not going to hit 2038. But if you are maintaining a MySQL database where someone years ago chose INT UNSIGNED for the timestamp column, that is a legitimate concern worth auditing now rather than in twelve years.
UTC Is Not a Timezone; That Distinction Matters
Unix timestamps are always in UTC. Not "kind of UTC" or "UTC-ish" โ always, definitionally UTC. A Unix timestamp is the count of seconds since the epoch in Coordinated Universal Time, period. It carries no timezone information itself and never needs to. The timezone question only arises when you convert that timestamp into a human-readable format for display.
This is where a persistent misconception causes real bugs: developers often think of timestamps as already being "in" their local timezone. They pull a timestamp from a database, convert it to a display string without specifying a timezone, and the result is formatted in the server's local timezone โ which is fine until the server is deployed in a different region, or until daylight saving kicks in, or until a user in another country sees a date that is off by hours.
The clean practice is to store and transmit timestamps as UTC integers or ISO 8601 UTC strings, and convert to local time only at the moment of display, using the viewer's timezone. This sounds obvious when stated plainly, but it is violated constantly because frameworks make local-time conversion the path of least resistance.
Leap Seconds and Why Unix Timestamps Pretend They Do Not Exist
Here is a genuinely strange fact: Unix timestamps do not represent leap seconds. When a leap second is inserted โ which has happened 27 times since 1972 โ Unix time does not add an extra second. Instead, the Unix timestamp at the leap second moment is repeated for two seconds, or smeared across a window, depending on the system's implementation.
The consequence is that if you count Unix seconds between two events that span a leap second insertion, your count will be off by one second from true elapsed time. For most applications, this is completely irrelevant โ your ride-share fare calculation does not need sub-second precision across UTC midnight on a particular June 30. But for systems that need to measure precise elapsed time (financial settlement, scientific instrumentation, network synchronization), this matters and requires using TAI (International Atomic Time) rather than Unix time, or explicitly accounting for known leap second offsets.
The practical takeaway: if you care about duration, and your durations span a potential leap second boundary, and you need accuracy to within a second, Unix timestamps are not sufficient by themselves. For everything else โ which is virtually all web application development โ you can safely ignore leap seconds entirely.
Parsing Timestamps Correctly
When receiving a timestamp from an external API or user input, validation matters more than most developers assume. An integer that claims to be a Unix timestamp could be in seconds, milliseconds, microseconds, or even nanoseconds. It could be a negative number representing a date before 1970. It could be zero, which is the epoch itself and a perfectly valid timestamp โ not a null or missing value, though some systems treat it as one, which is a subtle and occasionally catastrophic assumption.
Before converting any external integer to a date, it is worth checking whether the resulting date is plausible for your application's domain. A user registration timestamp of zero means your user registered at midnight UTC on January 1, 1970, which is almost certainly a data error. A timestamp of 9999999999999 places the date in the year 317,000, which is also probably not a valid registration date. These sanity checks are simple to add and prevent the category of bug where malformed data silently produces garbage that only surfaces months later in analytics reports.
Unix timestamps are elegant precisely because they strip time down to a single, unambiguous integer. That simplicity is the feature. The conversion in and out of that integer โ getting the units right, applying the correct timezone for display, handling edge cases sensibly โ is where the real work lives.