What Is a Unix Timestamp? Epoch Time, Seconds vs Milliseconds, and the 2038 Problem
CodexFuse Team · 2026-11-06T09:31:21.566Z · 24 min read min read
What Is a Unix Timestamp? Epoch Time, Seconds vs Milliseconds, and the 2038 Problem
If you have ever wondered what is a Unix timestamp, you have probably stared at a number like 1793923200 and asked what it could possibly mean. It looks like a random ten-digit code, but it is a date. A Unix timestamp is a single number that names one exact moment in time, and once you know the rule for reading it, you can decode any timestamp you meet in an API response, a database row, or a log file.
This guide explains the rule in plain English. You will learn what the number counts, why it starts on 1 January 1970, how to tell seconds from milliseconds at a glance, how to convert a timestamp in Python, JavaScript, SQL, and Excel, and what the Year 2038 problem really is. If you want to skip the reading and convert a value right now, a Unix timestamp converter does the job in your browser.
The rest of this page teaches you what that tool is actually doing.
Timestamps show up wherever software runs on a server, so this guide sits in the same hosting lane as our VPS hosting guide: the APIs, logs, and databases below almost always live on a virtual private server, and their timestamps are how those systems agree on when things happened.
What Is a Unix Timestamp?
A Unix timestamp, also called epoch time, Unix time, or POSIX time, is the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970. That starting moment is called the Unix epoch. Every timestamp is simply a distance from it: a positive number counts seconds after the epoch, and a negative number counts seconds before it.
Think of it as a stopwatch that started at midnight on 1 January 1970 and has never stopped. The stopwatch shows 0 at the epoch itself, 86400 exactly one day later, and about 1.79 billion as you read this in November 2026. At midnight UTC on 6 November 2026, the stopwatch read 1793923200.
By the time you finish this page, it will have ticked a few hundred higher, because it gains exactly one second every second.
The reason software loves this format is that a timestamp is one plain integer with no time zone attached. It means the same instant in New York, London, and Tokyo, it sorts correctly with ordinary number comparison, and subtracting two timestamps gives you the exact number of seconds between two events. Databases store it cheaply, APIs pass it without formatting arguments, and log files stay readable across machines.
Three facts about the number are worth fixing in your memory. Timestamp 0 is the epoch itself, 1 January 1970 at midnight UTC. The value -86400 is one day earlier, 31 December 1969.
And 86400 seconds is exactly one day, because Unix time defines every day as 24 hours times 60 minutes times 60 seconds. To convert any value you meet without doing the arithmetic by hand, the Unix timestamp converter does it in the browser.
| Unix timestamp | Date and time (UTC) | Why it matters |
|---|---|---|
| 0 | 1 January 1970, 00:00:00 | The epoch, where the count starts |
| 86400 | 2 January 1970, 00:00:00 | One day is 86,400 seconds |
| -86400 | 31 December 1969, 00:00:00 | Negative values reach before the epoch |
| 1000000000 | 9 September 2001, 01:46:40 | One billion seconds, the "billennium" |
| 1234567890 | 13 February 2009, 23:31:30 | The famous ascending-digits timestamp |
| 1700000000 | 14 November 2023, 22:13:20 | 1.7 billion seconds |
| 1746835200 | 10 May 2025, 00:00:00 | A recent round date developers use as an example |
| 1791158400 | 5 October 2026, 00:00:00 | A date from this autumn |
| 1793923200 | 6 November 2026, 00:00:00 | Midnight UTC on the day this guide was written |
| 1800000000 | 15 January 2027, 08:00:00 | 1.8 billion seconds, about 70 days after this guide |
| 2000000000 | 18 May 2033, 03:33:20 | 2 billion seconds |
| 2147483647 | 19 January 2038, 03:14:07 | The largest 32-bit signed timestamp (see the 2038 section) |
The count has been running for 20763 days as of 6 November 2026. That is a long time for one stopwatch, and the next section explains why engineers picked that particular starting line.
Why January 1, 1970? The Story of the Epoch
The epoch is 1 January 1970 because it was a practical choice, not a cosmic one. Unix was under active development at Bell Labs in the late 1960s and early 1970s, and its engineers needed a fixed starting point for timekeeping. They picked a round, recent date near the time they were working, and it stuck.
Early Unix systems actually counted time in sixtieths of a second using a 32-bit unsigned integer, and the epoch moved at least once during development before settling on 1970. The unit later changed to whole seconds, which is the convention every modern system uses. The POSIX standard then locked the definition in: Unix time is the count of non-leap seconds since the epoch, with every day defined as exactly 86,400 seconds.
The choice matters less than the agreement. Because every major operating system, database, and programming language adopted the same starting point, a timestamp produced by a Python script on a Linux server means exactly the same thing to a JavaScript app in a browser and a PostgreSQL database in another country. No other date system in computing has that level of universal agreement.
How to Read a Unix Timestamp in 5 Steps
Reading a timestamp by eye is a small skill, and it follows the same five steps every time. Work through them once with a real value, and the numbers stop looking random.
- Count the digits. Ten digits means the value is in seconds; thirteen digits means milliseconds. If the value has any other length, something upstream is wrong, and you should check the source before trusting it.
- Divide by 1000 if it is in milliseconds. JavaScript's Date.now() returns milliseconds, so a thirteen-digit value becomes a ten-digit seconds value when you divide by 1000 and drop the fraction.
- Sanity-check the year. A current-era seconds timestamp starts with 1.7 or 1.8. If your converted date lands in 1970, you fed seconds to something expecting milliseconds. If it lands thousands of years ahead, you fed milliseconds to something expecting seconds.
- Add the seconds to the epoch. The date is 1 January 1970 00:00:00 UTC plus the timestamp. For 1793923200, that arithmetic gives 6 November 2026 at midnight UTC.
- Convert to local time only at the end. The timestamp itself has no time zone, so do the UTC math first and apply your local offset only when you display the result to a person.
Try the steps on 1800000000. It has ten digits, so it is seconds. Adding it to the epoch gives 15 January 2027 at 08:00:00 UTC.
From midnight on 6 November 2026, that milestone is 6076800 seconds away, which is 70.33333333333333 days. It is the next round number the timestamp will hit, and it arrives about ten weeks after this guide was written.
Seconds vs Milliseconds: The 10-Digit vs 13-Digit Rule
The single most common Unix timestamp mistake is mixing up seconds and milliseconds. The original Unix convention counts seconds, and most Unix utilities, databases, and APIs still do. JavaScript, Java, and a few other ecosystems count milliseconds instead, because modern apps often need sub-second precision for animations, performance measurement, and real-time features.
The unix timestamp seconds vs milliseconds question has a simple answer for any date in the current era: a 10 digit vs 13 digit timestamp tells you the unit. A seconds timestamp today has ten digits, like 1793923200. The same instant in milliseconds has thirteen digits, like 1793923200000.
The rule holds for every date between 9 September 2001, when seconds timestamps first reached ten digits, and 20 November 2286, when they will reach eleven.
The digit-count rule is a rule of thumb, not a law. It breaks for old dates, negative timestamps, and far-future dates, so always check the documentation of the API you are reading and sanity-check the year after converting. An eleven- or twelve-digit value almost always means something went wrong upstream, and a value with fewer than ten digits is usually a date from before 2001 or a bug.
| Unit | Digits today | Same instant: 6 November 2026, 00:00:00 UTC | Who uses it |
|---|---|---|---|
| Seconds | 10 | 1793923200 | Unix tools, Python time.time(), most APIs, PostgreSQL, JWT claims |
| Milliseconds | 13 | 1793923200000 | JavaScript Date.now(), Java System.currentTimeMillis() |
| Microseconds | 16 | 1793923200000000 | High-precision logging, some databases |
| Nanoseconds | 19 | 1793923200000000000 | Specialized timing, Go time.Time internals |
The bug this causes is dramatic in both directions. Pass seconds to JavaScript's Date constructor, which expects milliseconds, and 1792051200 becomes 21 January 1970 (1970-01-21T17:47:31.200Z) instead of 15 October 2026. Pass milliseconds to something expecting seconds, and the same instant lands in the year 58,757, roughly 56,700 years from now.
Both failure modes are easy to spot once you know the digit rule, and both are easy to prevent by dividing or multiplying by 1000 at the boundary between systems.
One place the trap hides in production is JSON Web Tokens. The exp and iat claims in a JWT are defined in seconds, so JavaScript code that compares them against Date.now() without dividing by 1000 will think every token expired in 1970 or never expires at all. Convert at the boundary, and the bug never reaches your users.
How to Convert a Unix Timestamp to a Date
Converting a timestamp to a readable date is the question behind how to convert unix timestamp values, and it has a one-line answer in every major language. The only real decision is remembering which unit your value is in. Multiply by 1000 first if your timestamp is in seconds and your language expects milliseconds, or divide by 1000 if it is the other way around.
In Python, use datetime.fromtimestamp with an explicit UTC time zone. The call datetime.fromtimestamp(1746835200, tz=timezone.utc) returns 10 May 2025 at midnight UTC. Always pass tz=timezone.utc, because fromtimestamp without a time zone returns your computer's local time, which silently shifts the answer by your UTC offset.
Note that utcfromtimestamp has been deprecated since Python 3.12, so do not copy it from old tutorials; the fromtimestamp form with tz=timezone.utc is the current recommended way.
In JavaScript, multiply seconds by 1000 and pass the result to the Date constructor. The call new Date(1792051200 * 1000).toISOString() returns "2026-10-15T08:00:00.000Z", where the Z means UTC. The current time in milliseconds is Date.now(), and the current time in seconds is Math.floor(Date.now() / 1000).
The .toISOString() method always prints UTC, which makes it the safest way to check your work.
In SQL, PostgreSQL uses SELECT to_timestamp(1746835200), which returns 2025-05-10 00:00:00+00, and MySQL uses SELECT FROM_UNIXTIME(1746835200) for the same job. SQLite uses SELECT datetime(1746835200, 'unixepoch'). One warning belongs here: FROM_UNIXTIME answers in the session time zone, so the same query can print different times on two servers configured differently.
Check the session time zone before trusting a MySQL result.
In Excel or Google Sheets, the formula is =A1/86400+DATE(1970,1,1), where A1 holds the timestamp in seconds. For milliseconds, divide by 86400000 instead. The number 25569 only works if the workbook uses the 1900 date system, which is the Windows default; older Mac workbooks that use the 1904 date system shift every date by four years.
Google Sheets also offers =EPOCHTODATE(A1), which returns UTC directly. If you would rather not write formulas at all, the Unix timestamp to date converter and the timestamp to date converter both handle the conversion in the browser.
| Language or tool | Get the current timestamp | Timestamp to date | Date to timestamp |
|---|---|---|---|
| Python | int(time.time()) | datetime.fromtimestamp(ts, tz=timezone.utc) | int(datetime(2025, 5, 10, tzinfo=timezone.utc).timestamp()) |
| JavaScript | Date.now() (milliseconds) | new Date(ts * 1000).toISOString() | Math.floor(new Date('2026-10-15T08:00:00Z').getTime() / 1000) |
| PostgreSQL | EXTRACT(EPOCH FROM NOW()) | SELECT to_timestamp(1746835200) | SELECT EXTRACT(EPOCH FROM TIMESTAMP '2024-03-13 00:00:00 UTC') |
| MySQL | SELECT UNIX_TIMESTAMP() | SELECT FROM_UNIXTIME(1746835200) | SELECT UNIX_TIMESTAMP('2024-03-13 00:00:00') |
| SQLite | SELECT strftime('%s', 'now') | SELECT datetime(1746835200, 'unixepoch') | SELECT strftime('%s', '2025-05-10 00:00:00') |
| Excel / Sheets | =(NOW()-25569)*86400 | =A1/86400+DATE(1970,1,1) | =(A1-25569)*86400 |
| Command line | date +%s | date -u -d @1791158400 (Linux) or date -u -r 1791158400 (macOS) | date -d '2026-10-05 UTC' +%s (Linux) |
Go, Java, PHP, Ruby, and C all have the same one-liners: Go uses time.Now().Unix() for seconds, Java uses Instant.now().getEpochSecond(), PHP uses time(), Ruby uses Time.now.to_i, and C uses time(NULL). The pattern never changes; only the spelling does. Pick your language's version from the table, mind the unit, and the conversion works the first time.
How to Convert a Date Back to a Unix Timestamp
Going the other direction is just as mechanical: take a date, pin it to UTC, and count the seconds from the epoch. The step people forget is the pinning. A date without a time zone is ambiguous, and two systems can turn the same "10 May 2025" into timestamps hours apart if one assumes UTC and the other assumes local time.
In Python, build an aware datetime and call .timestamp(). The expression int(datetime(2025, 5, 10, tzinfo=timezone.utc).timestamp()) returns 1746835200. The tzinfo=timezone.utc part is the whole trick: without it, Python assumes your local time zone, and the result shifts by your offset from UTC.
In JavaScript, Date.parse or the Date constructor with an ISO string does the job. The call Math.floor(Date.parse('2026-10-15T08:00:00Z') / 1000) returns 1792051200. The Z at the end of the string marks it as UTC.
A date-only string like '2026-10-15' also parses as UTC in JavaScript, but a date-time string without a zone, like '2026-10-15 08:00:00', parses as local time, which is a related trap that shifts birthdays and deadlines by a day for some users.
In SQL, PostgreSQL's EXTRACT(EPOCH FROM TIMESTAMP '2024-03-13 00:00:00 UTC') returns 1710288000, MySQL's UNIX_TIMESTAMP('2024-03-13 00:00:00') returns the same value in the session time zone, and SQLite's strftime('%s', '2025-05-10 00:00:00') does the equivalent. In a spreadsheet, =(A1-25569)*86400 turns a date cell into seconds. If you prefer a tool to the formula, the date to Unix timestamp converter takes a date and returns the timestamp directly.
One habit saves more debugging time than any other here: always convert through UTC, and only apply a local time zone when you display the result. Store UTC, compute in UTC, and let the presentation layer worry about what the clock on the wall says.
What Timezone Is a Unix Timestamp In?
A Unix timestamp is in no time zone at all. It is UTC by definition, which is exactly why it works as a universal reference. The number names an instant, not a clock reading, and the clock reading you display depends entirely on the time zone you choose when you render it.
Take 1710288000, which is 13 March 2024 at 00:00 UTC. Rendered in New York it is 12 March at 19:00 EST. Rendered in Los Angeles it is 12 March at 16:00 PST.
Rendered in Mumbai it is 13 March at 05:30 IST, and in Tokyo it is 13 March at 09:00 JST. One number, one instant, five different wall-clock readings, and none of them is more correct than the others.
This is also why Unix time is immune to daylight saving time. UTC has no spring-forward or fall-back, so the count never skips or repeats an hour. The danger sits in the conversion step: turning a timestamp into local time around a DST transition can skip an hour that never existed or repeat an hour that happened twice.
A timestamp that converts to 10 May in UTC can render as 9 May in New York, which surprises developers the first time they see it in a report.
The practical rule is simple and worth repeating: store the timestamp, compute with the timestamp, and convert to local time only at the moment something is shown to a person. Every bug in this area comes from converting too early and then doing arithmetic on the converted value.
Where Unix Timestamps Show Up Every Day
Unix timestamps are the default way software records when things happen, and you meet them constantly even if you never see the raw number. APIs return them in almost every response that includes a time, because a single integer crosses language and time-zone boundaries without any formatting negotiation. JWT access tokens carry exp and iat claims in seconds, cache entries carry TTL values in seconds, and rate limiters count windows in seconds.
Databases store them as integers or as native timestamp types built on the same count. PostgreSQL's TIMESTAMPTZ, MySQL's TIMESTAMP, and SQLite's integer columns all trace back to the epoch, and sorting a table by a timestamp column is just sorting numbers. Log files stamp every line with one, which is how engineers reconstruct the exact order of events across a dozen servers after an outage.
Git records every commit with a timestamp, and file systems record creation and modification times the same way.
On a typical virtual private server, the same timestamp appears in the web server's access log, the application's database rows, and the cron jobs that run nightly backups. Cron itself schedules by wall-clock time, but the jobs it triggers often record their runs as timestamps, so one number ties the schedule to the result. When something goes wrong at 03:00 UTC, the timestamp is the one fact every log agrees on.
The reason this matters for a beginner is that timestamps are not an academic curiosity. They are the working format of time in production software, and the first time you debug an API, read a server log, or inspect a database row, you will meet one. Knowing the digit rule and the conversion one-liners turns that meeting from a mystery into a thirty-second check.
What Is the Year 2038 Problem?
The unix timestamp 2038 problem is a real, dated limit in how some older systems store time. A signed 32-bit integer can hold values from -2147483648 to 2147483647. Counted in seconds from the epoch, that maximum is reached at 03:14:07 UTC on 19 January 2038.
One second later, at 03:14:08, the value overflows and wraps around to -2147483648, which decodes as 1901-12-13 20:45:52 UTC.
The last valid 32-bit second is 03:14:07 UTC on 19 January 2038, and the overflow lands one second later at 03:14:08, flipping a date in 2038 into a date in 1901. Any system still storing time as a signed 32-bit integer will, at that moment, start believing it is more than 136 years in the past. The effect on real software depends on what the time is used for: a sorting routine would misorder every record, a certificate check would reject everything as expired, and a scheduled job would never run again.
Only systems still using a signed 32-bit time_t are affected. That means older or resource-constrained 32-bit embedded systems and firmware, legacy file formats such as ext2 and ext3 inodes, old database schemas with 32-bit timestamp columns, and old 32-bit binary protocols. The bug has already bitten in small ways: a system does not need to reach 2038 to fail, it only needs to represent a date past 2038, so 30-year mortgages, 15-year certificates, and long-dated bonds already cross the line.
Documented early cases include an AOLserver timeout overflow in May 2006, a Microsoft Exchange anti-malware failure on 1 January 2022, and an Oracle Access Management cookie expiry problem in March 2022.
Most of the software you use every day is already safe. Modern 64-bit operating systems and compilers use a 64-bit time_t by default, which stays valid for about 292 billion years. JavaScript is not affected by the 2038 problem at all, because its Date stores a 64-bit float of milliseconds and stays valid until the year 275760.
Python uses arbitrary-precision integers and has no upper limit at all. The fix, switching the time representation to a signed 64-bit integer, is already the default almost everywhere: Linux kernel 5.6 added 64-bit time_t support on 32-bit architectures in 2020, glibc 2.34 shipped it in August 2021, MySQL 8.0.28 handles 64-bit values in FROM_UNIXTIME and UNIX_TIMESTAMP, and MariaDB 11.5.1 extended its TIMESTAMP type to an unsigned 32-bit range reaching 7 February 2106.
| System | Affected by 2038? | Why |
|---|---|---|
| 32-bit embedded systems and old firmware | Yes | Still store time as a signed 32-bit integer |
| Legacy file formats (ext2, ext3, reiserFS) | Yes | Inode timestamps are 32-bit fields |
| Old 32-bit database schemas | Yes | 32-bit timestamp columns overflow at the limit |
| Modern 64-bit operating systems | No | 64-bit time_t, valid for about 292 billion years |
| JavaScript (Date) | No | 64-bit float of milliseconds, valid to the year 275760 |
| Python (datetime) | No | Arbitrary-precision integers, no upper limit |
| Current MySQL and MariaDB | No | 64-bit handling since MySQL 8.0.28; MariaDB TIMESTAMP to 2106 |
From midnight UTC on 6 November 2026, the overflow is 353560447 seconds away, which is 4092.134803240741 days. That sounds far off, and for most readers it is. The useful takeaway is not to worry about 2038, but to store any new timestamp as a 64-bit integer, a BIGINT column, or a TIMESTAMPTZ field, so the systems you build today never join the list of things that break that morning.
Does Unix Time Count Leap Seconds?
Unix time does not count leap seconds, and every Unix day is exactly 86,400 seconds long. The POSIX standard defines the count as the number of non-leap seconds since the epoch, which means the extra second inserted into real UTC during a leap second has no timestamp of its own. During a positive leap second, the Unix count simply repeats one second.
Since 1972, 27 leap seconds have been added to UTC to keep it in step with the Earth's rotation. The last one came at the end of 31 December 2016. The leap second that night was 23:59:60 UTC, and Unix time has no number for it: the timestamp 1483228799 is 23:59:59, and 1483228800 is 00:00:00 on 1 January 2017.
Atomic time, TAI, now runs 37 seconds ahead of UTC because of those 27 insertions plus the initial 10-second offset.
The practical consequence is small but real: subtracting two timestamps that straddle a leap second can be off by one second, because the count pretends the extra second never happened. For almost all software this does not matter, and it is why the Python documentation says leap seconds are ignored by fromtimestamp, and MDN says Date.now, Date.parse, and Date.UTC all return values with leap seconds ignored. Only scientific work and high-frequency financial timing need to care.
A rare variant is worth one line so it never confuses you: some Linux systems configured with "right" time zone data do count leap seconds, and their clocks run 27 seconds ahead of ordinary POSIX time. That is not Unix time, it is a different convention, and you will almost certainly never meet it.
Unix Timestamp Mistakes That Break Real Code
Most timestamp bugs come from a short list of mistakes, and all of them are easy to prevent once you have seen them. The table below collects the ones that actually break production code, with the symptom each one produces and the fix that stops it.
| Mistake | What happens | Fix |
|---|---|---|
| Feeding seconds to JavaScript's Date | 1792051200 becomes 21 January 1970 | Multiply by 1000 first: new Date(ts * 1000) |
| Feeding milliseconds to a seconds API | The date lands tens of thousands of years ahead | Divide by 1000 first: Math.floor(Date.now() / 1000) |
| Comparing JWT exp against Date.now() | Every token looks expired or never expiring | Divide Date.now() by 1000; JWT claims are seconds |
| Calling fromtimestamp without a time zone | Python returns local time, shifted by your offset | Always pass tz=timezone.utc |
| Trusting MySQL FROM_UNIXTIME blindly | Two servers print different times for one value | Check the session time zone first |
| Putting a millisecond value in Excel | Excel keeps only 15 significant digits, so precision is lost | Divide down to seconds before pasting |
| Copying utcfromtimestamp from old tutorials | Deprecated code that returns a naive datetime | Use fromtimestamp(ts, tz=timezone.utc) |
| Storing new timestamps in 32-bit columns | The column overflows on 19 January 2038 | Use BIGINT or TIMESTAMPTZ for anything new |
The pattern behind every row is the same: the timestamp itself is never wrong, the unit or the time zone at the boundary is. Convert at the boundary, check the year, and the bug shows itself before your users ever see it.
Convert a Timestamp Right Now
You now know enough to read any Unix timestamp you meet. The last step is practice, and the fastest practice is a live conversion. Paste a value into the Unix timestamp converter to see its date, or paste a date to get its timestamp.
The converter handles seconds and milliseconds, so you can check your digit-count reading against a real answer in seconds.
The numbers in this guide were all computed, not guessed. Here is the Python session that produced them, run on 6 November 2026, so you can re-run it yourself and see the same results.
import datetime
UTC = datetime.timezone.utc
print("seconds in one day:", 24*60*60) # 86400
print("seconds in one week:", 7*24*60*60) # 604800
print("seconds in one 365-day year:", 365*24*60*60) # 31536000
print("midnight 2026-11-06 UTC:", 1793923200) # 1793923200
print("seconds left until 1.8 billion:", 1800000000-1793923200) # 6076800
print("days left until 1.8 billion:", (1800000000-1793923200)/86400) # 70.33333333333333
print("seconds left until 2038 overflow:", 2147483647-1793923200) # 353560447
print("days left until 2038 overflow:", (2147483647-1793923200)/86400) # 4092.134803240741
print("days since the epoch:", 1793923200//86400) # 20763
print("milliseconds now-ish:", 1793923200*1000) # 1793923200000
print("microseconds:", 1793923200*1000000) # 1793923200000000
print("nanoseconds:", 1793923200*1000000000) # 1793923200000000000
print("Excel serial for 2026-10-05:", 1791158400/86400+25569) # 46300.0
print("ms value / 1000 =", 1792051200000/1000) # 1792051200.0
print("1.7 billion ->", datetime.datetime.fromtimestamp(1700000000, tz=UTC)) # 2023-11-14 22:13:20+00:00
print("2 billion ->", datetime.datetime.fromtimestamp(2000000000, tz=UTC)) # 2033-05-18 03:33:20+00:00
print("32-bit max ->", datetime.datetime.fromtimestamp(2147483647, tz=UTC)) # 2038-01-19 03:14:07+00:00
A Unix timestamp is one number, one rule, and one starting point. Learn the digit rule, convert through UTC, mind the unit at every boundary, and the ten-digit numbers that fill your logs and APIs become dates you can read at a glance.
Sources
- Wikipedia, "Unix time" — definition, leap-second handling, 32-bit and 64-bit ranges. https://en.wikipedia.org/wiki/Unix_time
- Wikipedia, "Year 2038 problem" — overflow moment, affected systems, early cases, per-platform fixes. https://en.wikipedia.org/wiki/Year_2038_problem
- Epochify, "Unix Timestamp Converter" — definition, conversion snippets, landmark table, 2038 section. https://epochify.dev/
- GlaeKit, "Unix Timestamp Explained" — why 1970, UTC anchoring, seconds-versus-milliseconds trap. https://glaekit.dev/blog/unix-timestamp-explained.html
- dev.to, willivan0706, "Unix timestamps explained — converting, formatting, and avoiding the common mistakes" — JS, Python, SQL, command-line conversions and the timezone trap. https://dev.to/willivan0706/unix-timestamps-explained-converting-formatting-and-avoiding-the-common-mistakes-2ei2
- QuickUtil, "Unix Timestamps Explained: The Complete Developer Guide" — history, per-language unit table, time zones and DST, 2038 fixes. https://www.quickutil.dev/blog/unix-timestamp-guide/
- JustWebWorld, "Unix Timestamp (Epoch Time) Explained: Convert to Date and IST" — Excel and Sheets formulas, leap-second dates, 1.8-billion milestone. https://justwebworld.com/unix-timestamp/
- DevToolry, "Unix Timestamp Explained: Seconds, ms, Excel and 2038" — worked bug examples, Excel caveats, 2038 affected lists. https://devtoolry.com/blog/unix-timestamps-explained
- InstaConvert, "The Year 2038 Problem, Explained" — overflow arithmetic, affected versus unaffected systems. https://www.instaconvert.app/timestamp-converter/blog/year-2038-problem-explained/
- MDN Web Docs, "Date" (JavaScript) — Date as milliseconds since the epoch, leap seconds ignored, maximum range. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
- Python Documentation, "datetime — Basic date and time types" — fromtimestamp, utcfromtimestamp deprecation since 3.12, leap seconds ignored. https://docs.python.org/3/library/datetime.html
Frequently Asked Questions
What is a Unix timestamp in simple terms?
A Unix timestamp is the number of seconds since midnight UTC on 1 January 1970. It is a single number that names one exact moment, with no time zone attached. The timestamp 0 is the epoch itself, 86400 is one day later, and a current timestamp has ten digits because about 1.79 billion seconds have passed since 1970.
How do I know if a timestamp is in seconds or milliseconds?
Count the digits. For any date in the current era, ten digits means seconds and thirteen digits means milliseconds. If the value has thirteen digits, divide by 1000 to get seconds.
Always sanity-check by converting and looking at the year: a date in 1970 means you fed seconds to something expecting milliseconds, and a date thousands of years ahead means the reverse.
How do I convert a Unix timestamp to a date?
In Python, use datetime.fromtimestamp(ts, tz=timezone.utc). In JavaScript, use new Date(ts * 1000).toISOString(). In PostgreSQL, use SELECT to_timestamp(ts), and in MySQL, SELECT FROM_UNIXTIME(ts).
In Excel, use =A1/86400+DATE(1970,1,1) for a timestamp in seconds. Or paste the value into a Unix timestamp converter and get the date instantly.
What timezone is a Unix timestamp in?
None. A Unix timestamp is UTC by definition and means the same instant everywhere on Earth. Time zones only enter when you convert the timestamp into a human-readable date for display.
Convert through UTC first, then apply the local offset at the very end.
What is the Year 2038 problem, and should I worry about it?
Signed 32-bit timestamps max out at 2,147,483,647, which is 03:14:07 UTC on 19 January 2038, and wrap to December 1901 one second later. It only affects systems still storing time as a signed 32-bit integer, mostly old embedded devices and legacy file formats. Modern 64-bit systems, JavaScript, and Python are unaffected.
If you store new timestamps as 64-bit integers, the problem never touches you.


