If you've ever opened a database row, an API response, or a log file and seen a number like 1700000000 sitting where a date should be, you've met a Unix timestamp. It looks meaningless until you know the rule: it's the count of seconds since a specific moment in 1970. Once you know that one fact, the number stops being cryptic and starts being one of the most useful values in software, because it sidesteps almost every problem that comes with storing dates as text.
This post covers what a Unix timestamp actually is, why it's anchored to that particular date and to UTC rather than any local timezone, the difference between second-based and millisecond-based timestamps (a distinction that causes more bugs than it should), and the Year 2038 problem, a real, dated technical limit that's still worth understanding even though most modern systems have already moved past it.
What a Unix timestamp actually counts
A Unix timestamp, also called epoch time, is the number of seconds that have elapsed since January 1, 1970, at 00:00:00 UTC. That instant is called the Unix epoch. Every timestamp is a distance from it: a positive number is that many seconds after the epoch, a negative number is that many seconds before it. As I write this, that count is somewhere north of 1.79 billion — a number that grows by exactly one, every second, everywhere on Earth, with no leap-second bookkeeping baked in.
Why 1970 specifically? There's no cosmic significance to the date. Unix was under active development at Bell Labs in the late 1960s and early 1970s, and engineers needed a reference point to measure time from. Picking the start of that decade was a practical, slightly arbitrary choice: round, recent, and close enough to "now" (for 1970) that the numbers involved wouldn't be unreasonably large. Earlier drafts of Unix time actually used different epochs before the community settled on January 1, 1970 as the standard. It stuck, and forty-plus years of infrastructure has been built on top of it since.
The more important design choice is that the count is anchored to UTC, not to any local timezone. This is what makes a timestamp genuinely useful for storage: the number 1700000000 means the exact same instant whether it's read in Tokyo, Toronto, or a server in a data center that has no idea where its users are. There's no ambiguity, no "which timezone was this saved in," no daylight-saving edge case to trip over. A formatted string like "11/14/2023 10:13 PM" can't make that claim on its own; you'd need to also store the timezone it was written in, and hope nobody forgets. A Unix timestamp is timezone-free by construction, which is exactly why it makes a good unix timestamp converter target: the conversion to a human-readable local date is a separate, deliberate step, done only when something needs to be displayed to a person. Store the number, convert for display, and you never have to reconcile two different ideas of "when."
Seconds vs. milliseconds: the bug almost everyone hits once
Here's a detail that trips up a lot of developers the first time they mix two systems together: not every timestamp uses the same unit. The original, and still most common, convention is seconds since the epoch, which is what the term "Unix time" traditionally means, and what most server-side languages and databases default to. But JavaScript's Date.now() and new Date().getTime() both return milliseconds since the epoch, not seconds. That single difference in unit is responsible for an enormous number of "why is this date wrong" bugs.
You can usually tell which unit you're looking at just by counting digits, and it's worth memorizing this rather than guessing each time. A seconds-based timestamp for a date anywhere in the current era is 10 digits long — 1700000000, for example. A milliseconds-based timestamp for the same instant is 13 digits — 1700000000000. If you see 13 digits and feed them into a function expecting seconds, you'll land on a date roughly 52,000 years in the future, because the function multiplies by 1000 again to get milliseconds and now you've got milliseconds-of-milliseconds. Go the other direction, feed a 10-digit seconds value into something expecting milliseconds, and you'll land on a date in January 1970, a few minutes after the epoch, because 1.7 billion milliseconds is only about 20 days.
That second failure mode is the one I see most often in the wild: a chart or a "last updated" field that stubbornly shows a date in January 1970 no matter what the actual data says. It's almost always a seconds value passed straight into a millisecond-expecting constructor without the * 1000 conversion. If you ever see "1970" show up somewhere it clearly shouldn't, check the unit before you check anything else; it's rarely a logic bug and almost always an off-by-a-factor-of-1000 problem. When you're converting between the two, be explicit about which one you're producing and which one you're consuming, especially when an API's documentation doesn't state it outright.
The Year 2038 problem, and how to actually work with timestamps
Some older and embedded systems store a Unix timestamp in a signed 32-bit integer, which can only represent whole numbers up to 2,147,483,647. Counting seconds from the 1970 epoch, that ceiling is reached at 03:14:07 UTC on January 19, 2038. One second later, the value wraps around to a large negative number, which most systems interpret as a date back in December 1901 rather than a date in 2038. That's the Year 2038 problem, and it's a direct mechanical consequence of the integer size, not a vague or hypothetical warning: the exact second it happens is fixed and calculable today.
Most systems built or updated in the last decade or so store timestamps as 64-bit integers, which push the same overflow out to a date roughly 292 billion years from now, which is to say it's effectively solved for anything modern. The real risk sits in older embedded devices, legacy databases, and any codebase where a timestamp column was defined as a 32-bit type years ago and never revisited. If you maintain something with a long deployment lifetime (firmware, industrial control systems, an old database schema), it's worth actually checking the column or variable type rather than assuming it's fine.
Beyond the 2038 edge case, the practical rule for day-to-day work is simple and worth stating plainly: store and pass timestamps in UTC, and convert to a local timezone only at the point where something is being shown to a person. Keep that conversion at the edge of your system, in the display layer, not baked into how the value is stored or passed between services. Every intermediate step, the database row, the API payload, the log entry, should carry the same unambiguous UTC-based number. That way a server in one timezone and a browser in another are always talking about the exact same instant, and the only place "which timezone" ever becomes a question is the final render.
Try it
GlaeKit's Unix Timestamp Converter handles both directions: paste a timestamp to get a readable date, or pick a date to get a timestamp, and it auto-detects seconds vs. milliseconds by digit count. Everything runs in your browser; nothing is uploaded.
Frequently asked questions
What is Unix time, exactly?
Unix time (also called epoch time) is the number of seconds elapsed since January 1, 1970, 00:00:00 UTC. It's a single, timezone-independent number used to represent a point in time in databases, logs, and APIs.
Why does Unix time start in 1970?
There's no special significance to the date; it was a practical, fairly arbitrary reference point chosen by the engineers developing Unix at Bell Labs in the early 1970s. It stuck as the standard and is now used far beyond Unix itself.
Is a timestamp measured in seconds or milliseconds?
It depends on the system. The traditional Unix convention is seconds, but JavaScript's Date.now() returns milliseconds. A quick way to tell them apart: a seconds-based timestamp for a current date is 10 digits long, while a milliseconds-based one is 13 digits.
What is the Year 2038 problem?
Systems that store a timestamp as a signed 32-bit integer can only count up to 2,147,483,647 seconds past the epoch. That limit is reached at 03:14:07 UTC on January 19, 2038, after which the value overflows to a negative number and is often misread as a date in 1901. Modern 64-bit systems aren't affected.
How do I convert a timestamp to my local timezone?
Store the raw timestamp in UTC and convert it only when displaying it to a user, using their browser or device's local timezone setting. A tool like GlaeKit's converter does this automatically, showing the equivalent local date and time for whatever timestamp you paste in.