Unix Timestamps: A Beginner's Guide to Time in Programming
Why every developer deals with '1695024000' and what to do when it doesn't mean what you think it means.
If you've ever debugged an API response and seen a number like 1695024000 where you expected a date, you've encountered a Unix timestamp. Every developer meets them eventually — usually with confusion, sometimes with frustration, eventually with grudging acceptance.
Unix timestamps are one of those concepts that's brilliantly simple in principle and quietly complicated in practice. Here's what they are, why they exist, and the gotchas that catch every developer eventually.
What a Unix timestamp is
A Unix timestamp (also called "Unix time" or "POSIX time") is the number of seconds that have elapsed since January 1, 1970, 00:00:00 UTC — the "Unix epoch." That's it. A single integer that increases by 1 every second.
The timestamp 1695024000 represents September 18, 2023, at 12:00:00 UTC. The timestamp 0 is the epoch itself. Negative timestamps represent dates before 1970.
The simplicity is the appeal:
- Timezone-agnostic. A timestamp is always UTC. No "is this in EST or PST?" ambiguity.
- Comparable. To check if event A happened before event B, just compare two integers.
- Arithmetic-friendly. To get the timestamp 24 hours from now, add
86400(24 * 60 * 60). To get a week ago, subtract604800. - Compact. A 32-bit integer can represent dates up to 2038. A 64-bit integer can represent dates billions of years in the future.
The 2038 problem
The classic Unix timestamp is a 32-bit signed integer. This means it can represent values from -2,147,483,648 to 2,147,483,647. The maximum positive value, 2,147,483,647, corresponds to January 19, 2038, at 03:14:07 UTC.
One second later, the timestamp would need to be 2,147,483,648 — but that exceeds the 32-bit signed integer range. Systems using 32-bit timestamps will roll over to -2,147,483,648, which corresponds to December 13, 1901.
This is the "Year 2038 problem" (Y2038). It affects systems that store timestamps as 32-bit integers — primarily older C code, embedded systems, and legacy databases.
The fix is straightforward: use 64-bit integers for timestamps. Most modern systems (Linux, macOS, modern databases) already use 64-bit timestamps and are unaffected. The risk is in older systems that haven't been updated — embedded devices, industrial controllers, legacy banking systems.
Seconds vs. milliseconds
JavaScript's Date.now() returns the timestamp in milliseconds, not seconds. So does Date.getTime(). This is a common source of bugs when JavaScript interacts with APIs that use seconds.
const ms = Date.now(); // 1695024000000
const seconds = Math.floor(ms / 1000); // 1695024000
To convert from milliseconds to seconds, divide by 1000. To convert from seconds to milliseconds, multiply by 1000. Always check the unit when integrating with a new API.
Some systems (notably Java) use nanosecond timestamps. The principle is the same; only the multiplier changes.
Timezone considerations
A timestamp is always UTC. But users want to see times in their local timezone. The conversion is:
- Parse the timestamp as UTC.
- Format it for the user's timezone.
In JavaScript:
const ts = 1695024000;
const date = new Date(ts * 1000); // Convert seconds to ms
const formatted = date.toLocaleString('en-US', { timeZone: 'America/New_York' });
// → "9/18/2023, 8:00:00 AM" (EDT, UTC-4)
The Intl.DateTimeFormat API handles timezone conversions correctly, including daylight saving time. Don't try to do timezone math yourself — the rules change, DST shifts, and historical timezone data is surprisingly complex.
Daylight saving time
Daylight saving time (DST) is the bane of every developer who works with timezones. The rules:
- DST starts and ends on different dates in different regions.
- Some regions don't observe DST at all (most of Asia, parts of Australia).
- The DST transition can be 1 hour forward ("spring forward") or 1 hour back ("fall back").
- The "fall back" transition creates an ambiguous hour — 1:30 AM happens twice.
- Historical DST rules have changed. The US changed its DST dates in 2007. The EU is considering abolishing DST.
If you're storing timestamps in a database, store them as UTC. Convert to local time only when displaying. Never store "local time" without an explicit timezone.
ISO 8601: the alternative
ISO 8601 is the standard date format that includes timezone information explicitly:
2026-09-18T12:00:00Z— UTC (theZsuffix means "Zulu time," which is UTC)2026-09-18T14:00:00+02:00— 2:00 PM in a UTC+2 timezone2026-09-18— date only (no time)2026-09— year and month only
ISO 8601 is human-readable, timezone-explicit, and sortable as text. It's the standard for API responses (JSON APIs typically return ISO strings, not Unix timestamps).
The tradeoff:
- ISO 8601 is human-readable and explicit about timezones. Bulky for storage (24+ characters vs 10 for a Unix timestamp).
- Unix timestamp is compact and arithmetic-friendly. Opaque to humans without a converter.
Most APIs use ISO 8601 for display and Unix timestamps for internal operations. Converting between them is a common task.
Common operations
Get current timestamp:
const now = Math.floor(Date.now() / 1000); // seconds
const nowMs = Date.now(); // milliseconds
Format a timestamp for display:
const ts = 1695024000;
const date = new Date(ts * 1000);
console.log(date.toISOString()); // "2023-09-18T12:00:00.000Z"
console.log(date.toLocaleString()); // Local format
Parse an ISO string into a timestamp:
const iso = "2026-09-18T12:00:00Z";
const ts = Math.floor(new Date(iso).getTime() / 1000);
console.log(ts); // 1789713600
Add 24 hours to a timestamp:
const now = Math.floor(Date.now() / 1000);
const tomorrow = now + 86400; // 60 * 60 * 24
Calculate the difference between two timestamps:
const diff = laterTs - earlierTs;
const days = Math.floor(diff / 86400);
const hours = Math.floor((diff % 86400) / 3600);
const minutes = Math.floor((diff % 3600) / 60);
Common pitfalls
1. Mixing seconds and milliseconds. Always check the unit. JavaScript uses ms; most APIs use seconds. Mixing them produces dates 50,000 years in the future or 50,000 years in the past.
2. Forgetting timezone when displaying. A timestamp is UTC. If you display it as local time without specifying the timezone, you may confuse users in different regions.
3. Storing local time as a timestamp. If you compute new Date('2026-09-18 12:00:00').getTime() without specifying a timezone, JavaScript uses the local timezone of the machine. This produces a different timestamp depending on where the code runs. Always specify the timezone explicitly.
4. Assuming a year has 365 days. Leap years exist. Use date arithmetic libraries (like date-fns or dayjs) for complex calculations.
5. Trusting client clocks. The user's clock can be wrong. If your app depends on the current time, fetch it from the server.
Converting locally
Whenever you need to convert between Unix timestamps and ISO 8601 (or any other format), run the conversion locally. Pasting timestamps into online tools sends them to a third-party server, which is fine for public data but problematic for internal APIs, debug logs, or anything with sensitive timestamps.
TextOpal's Timestamp Converter handles:
- Unix seconds and milliseconds → ISO 8601
- ISO 8601 → Unix seconds and milliseconds
- 14 common timezones (UTC, Moscow, London, New York, Tokyo, etc.)
- Relative time ("3 days ago", "in 2 hours")
- Live updates (the relative time refreshes every second)
Everything runs in your browser. Your timestamps never leave your device.
The deeper story
Time in programming is a rabbit hole. Timezones are political (countries change their DST rules periodically). Leap seconds exist (occasionally, a minute has 61 seconds). The Gregorian calendar wasn't adopted universally until the 20th century. The Julian calendar is still used by some Orthodox churches.
For most applications, you don't need to worry about these edge cases. Use UTC for storage, ISO 8601 for display, and a good date library for arithmetic. Convert timestamps to human-readable formats with a local tool. Don't reinvent what the libraries have already solved.
But knowing the basics — what a timestamp is, why it's UTC, how to convert it — saves you from the bugs that catch every developer eventually. The next time you see 1695024000 in an API response, you'll know exactly what it means.