Unix Timestamps Explained: What They Are, How They Work & How to Convert Them

If you've ever worked with APIs, databases, or log files, chances are you've encountered a long integer like 1738368000 and wondered what it meant. That number is a Unix timestamp—one of the most fundamental concepts in computing for representing time. Understanding timestamps is essential for anyone who builds software, works with data, or manages servers.

In this comprehensive guide, we'll cover everything you need to know about Unix timestamps: what they are, where they come from, how to convert them in popular programming languages, and the critical issues you should be aware of—including the infamous Year 2038 problem.

What Is a Unix Timestamp?

A Unix timestamp (also known as epoch time, POSIX time, or simply Unix time) is the number of seconds that have elapsed since January 1, 1970, 00:00:00 Coordinated Universal Time (UTC). This specific moment—midnight on the first day of 1970—is known as the Unix epoch.

For example, the Unix timestamp 1738368000 corresponds to February 1, 2026 00:00:00 UTC. Every second that passes increments this counter by one. Moments before the epoch are represented as negative numbers: the timestamp -86400 refers to December 31, 1969.

🎯 Key Characteristics of Unix Timestamps

  • Universal: The same timestamp means the same instant everywhere in the world
  • Timezone-independent: Always based on UTC, no daylight saving confusion
  • Compact: A single integer represents an exact moment in time
  • Sortable: Simple numeric comparison determines chronological order
  • Language-agnostic: Supported natively in virtually every programming language

Because a timestamp is just a number, it is incredibly easy to store, transmit, compare, and perform arithmetic on. Want to know how many seconds elapsed between two events? Simply subtract one timestamp from another. Need to find a date 30 days in the future? Add 30 * 86400 (the number of seconds in 30 days) to the current timestamp. This simplicity is precisely why Unix timestamps have become the de facto standard for timekeeping in software systems worldwide.

The History of the Unix Epoch

The story of the Unix epoch begins at Bell Labs in the late 1960s and early 1970s, where Ken Thompson, Dennis Ritchie, and their colleagues were building the Unix operating system. Early versions of Unix needed a way to track file creation and modification times, so the developers implemented a simple counter.

The very first Unix time implementation didn't actually start at January 1, 1970. The original PDP-7 Unix system used a counter that measured time in 60ths of a second (sixtieths, matching the system clock frequency) starting from January 1, 1971. However, this approach had a serious limitation: using a 32-bit integer counting at 60 Hz meant the clock would overflow in only about 2.5 years.

Why January 1, 1970?

To fix the overflow issue, the engineers made two critical changes. First, they switched from counting in 60ths of a second to counting in whole seconds, which dramatically extended the range. Second, they moved the epoch backward to January 1, 1970—a round date that was recent enough to be practical yet far enough back to cover any files that had already been created on the system. The choice was pragmatic rather than deeply symbolic: it was simply a convenient starting point that gave the counter a useful range well into the future.

With a signed 32-bit integer counting in seconds, the new system could represent dates from December 13, 1901 through January 19, 2038—a span of roughly 136 years. At the time, a range extending 68 years into the future seemed more than sufficient. As we'll discuss later, that assumption has created one of computing's most well-known time bombs.

How Unix Timestamps Work

At its core, a Unix timestamp is simply an integer that increments by one every second. The system is almost deceptively simple:

// Mapping between timestamps and dates Timestamp 0 → January 1, 1970 00:00:00 UTC Timestamp 86400 → January 2, 1970 00:00:00 UTC (1 day = 86,400 seconds) Timestamp 1000000000 → September 9, 2001 01:46:40 UTC Timestamp 1738368000 → February 1, 2026 00:00:00 UTC Timestamp -86400 → December 31, 1969 00:00:00 UTC

To convert a timestamp to a human-readable date, you divide the total seconds into years, months, days, hours, minutes, and remaining seconds—accounting for leap years and varying month lengths. In practice, every major programming language provides built-in functions to handle this conversion, so you almost never do it manually.

32-Bit vs 64-Bit Timestamps

The storage format of a Unix timestamp determines its range. The two most common representations are:

Property 32-Bit Signed Integer 64-Bit Signed Integer
Maximum Value 2,147,483,647 9,223,372,036,854,775,807
Latest Date January 19, 2038 03:14:07 UTC ~292 billion years from now
Earliest Date December 13, 1901 20:45:52 UTC ~292 billion years ago
Total Range ~136 years ~584 billion years
Storage Size 4 bytes 8 bytes

Most modern operating systems, programming languages, and databases have already transitioned to 64-bit timestamps. Linux moved to 64-bit time_t on 64-bit systems long ago, and 32-bit Linux kernels added 64-bit time support in kernel version 5.6 (released 2020). JavaScript's Date object uses a 64-bit floating-point number internally, giving it a range of approximately ±285,616 years from the epoch.

Timestamps vs Human-Readable Dates

There are two fundamentally different ways to represent a point in time in software:

Feature Unix Timestamp Human-Readable Date
Example 1738368000 2026-02-01T00:00:00Z
Readability Machine-friendly Human-friendly
Sorting Simple numeric sort Requires date parsing
Arithmetic Add/subtract seconds directly Requires date library functions
Timezone Always UTC Can include timezone offset
Storage Size 4–8 bytes 20–30+ bytes as string
Ambiguity None (absolute value) Can be ambiguous without timezone

In most applications, the best practice is to store dates as Unix timestamps (or database-native datetime types) and convert to human-readable format only when displaying to users. This avoids timezone ambiguity, simplifies comparisons, and reduces storage overhead.

Converting Timestamps in JavaScript

JavaScript is the most widely used language on the web, so it's often the first place developers encounter timestamp conversions. JavaScript's Date object works with milliseconds since the epoch (not seconds), so you'll frequently need to multiply or divide by 1000.

Getting the Current Timestamp

// Current timestamp in MILLISECONDS const msTimestamp = Date.now(); console.log(msTimestamp); // e.g. 1738368000000 // Current timestamp in SECONDS (Unix standard) const unixTimestamp = Math.floor(Date.now() / 1000); console.log(unixTimestamp); // e.g. 1738368000 // Alternative: using a Date object const now = new Date(); console.log(now.getTime()); // milliseconds since epoch

Converting a Timestamp to a Date

// Convert Unix timestamp (seconds) to Date object const timestamp = 1738368000; const date = new Date(timestamp * 1000); // multiply by 1000 for ms console.log(date.toUTCString()); // "Sun, 01 Feb 2026 00:00:00 GMT" console.log(date.toISOString()); // "2026-02-01T00:00:00.000Z" console.log(date.toLocaleString()); // "2/1/2026, 12:00:00 AM" (varies by locale)

Converting a Date String to a Timestamp

// From an ISO 8601 string const ts = Math.floor(new Date("2026-02-01T00:00:00Z").getTime() / 1000); console.log(ts); // 1738368000 // From individual components (months are 0-indexed!) const ts2 = Math.floor( Date.UTC(2026, 1, 1, 0, 0, 0) / 1000 ); console.log(ts2); // 1738368000

⚠️ Common JavaScript Pitfall

JavaScript's Date object uses milliseconds, while Unix timestamps are traditionally in seconds. Forgetting to multiply or divide by 1000 is one of the most common timestamp bugs. If your date lands in January 1970, you probably forgot to multiply by 1000. If it's in the year 56,000+, you probably forgot to divide.

Converting Timestamps in Python

Python provides two main modules for working with timestamps: the time module (lower-level) and the datetime module (higher-level, more feature-rich).

Getting the Current Timestamp

import time import datetime # Current Unix timestamp as a float current_ts = time.time() print(current_ts) # e.g. 1738368000.123456 # As an integer (seconds only) print(int(time.time())) # e.g. 1738368000 # Using datetime module now = datetime.datetime.now(datetime.timezone.utc) ts = int(now.timestamp()) print(ts) # e.g. 1738368000

Converting a Timestamp to a Date

import datetime timestamp = 1738368000 # Convert to UTC datetime dt = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc) print(dt) # 2026-02-01 00:00:00+00:00 # Format as a readable string print(dt.strftime("%B %d, %Y %H:%M:%S UTC")) # February 01, 2026 00:00:00 UTC # Convert to ISO 8601 print(dt.isoformat()) # 2026-02-01T00:00:00+00:00

Converting a Date String to a Timestamp

import datetime # From an ISO 8601 string dt = datetime.datetime.fromisoformat("2026-02-01T00:00:00+00:00") ts = int(dt.timestamp()) print(ts) # 1738368000 # From a custom format dt = datetime.datetime.strptime("2026-02-01", "%Y-%m-%d") dt = dt.replace(tzinfo=datetime.timezone.utc) print(int(dt.timestamp())) # 1738368000

Converting Timestamps in Other Languages

Virtually every programming language supports Unix timestamps. Here's a quick reference for several popular ones:

PHP

// Get current timestamp $timestamp = time(); // Convert timestamp to date string echo date('Y-m-d H:i:s', 1738368000); // 2026-02-01 00:00:00 // Convert date string to timestamp $ts = strtotime('2026-02-01 00:00:00 UTC');

Java

// Get current timestamp (seconds) long timestamp = System.currentTimeMillis() / 1000; // Using java.time (Java 8+) import java.time.Instant; Instant instant = Instant.ofEpochSecond(1738368000L); System.out.println(instant); // 2026-02-01T00:00:00Z

C# / .NET

// Get current timestamp long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); // Convert timestamp to DateTimeOffset var dto = DateTimeOffset.FromUnixTimeSeconds(1738368000); Console.WriteLine(dto); // 2/1/2026 12:00:00 AM +00:00

Go

package main import ("fmt"; "time") func main() { // Current timestamp ts := time.Now().Unix() // Convert to time.Time t := time.Unix(1738368000, 0) fmt.Println(t.UTC()) // 2026-02-01 00:00:00 +0000 UTC }

Bash / Command Line

# Get current timestamp date +%s # Convert timestamp to date (GNU/Linux) date -d @1738368000 # Sun Feb 1 00:00:00 UTC 2026 # Convert timestamp to date (macOS) date -r 1738368000

ISO 8601: The Standard Date Format

While Unix timestamps are ideal for machines, humans need a standardized string format too. That's where ISO 8601 comes in. Defined by the International Organization for Standardization, ISO 8601 (and its internet profile RFC 3339) specifies an unambiguous date-time format:

// ISO 8601 format examples "2026-02-01" // Date only "2026-02-01T15:30:00" // Date and time (local) "2026-02-01T15:30:00Z" // Date and time in UTC "2026-02-01T15:30:00+05:30" // Date and time with offset "2026-02-01T15:30:00.123Z" // With milliseconds

The "Z" suffix stands for "Zulu time" (military parlance for UTC) and indicates the time is in Coordinated Universal Time. When a timezone offset is included (like +05:30), the time is expressed relative to UTC.

💡 Best Practice

When exchanging dates between systems, always use either Unix timestamps or ISO 8601 strings with explicit timezone information. Ambiguous date strings like "02/01/2026" (is it February 1st or January 2nd?) without timezone data are a leading cause of date-related bugs in software.

Timestamps in Databases

Every major database system has built-in support for timestamps, though the implementation details vary. Understanding how your database handles time is crucial for building reliable applications.

MySQL / MariaDB

-- Store timestamps CREATE TABLE events ( id INT AUTO_INCREMENT PRIMARY KEY, event_name VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, event_time INT UNSIGNED -- store as Unix timestamp ); -- Convert between formats SELECT UNIX_TIMESTAMP(); -- current timestamp SELECT FROM_UNIXTIME(1738368000); -- '2026-02-01 00:00:00' SELECT UNIX_TIMESTAMP('2026-02-01 00:00:00'); -- 1738368000

MySQL's TIMESTAMP column type stores values internally as UTC and converts to the connection's timezone on retrieval. The DATETIME type, in contrast, stores the literal date and time with no timezone conversion. For most applications, TIMESTAMP is the better choice because it handles timezone differences automatically.

PostgreSQL

-- PostgreSQL timestamp types CREATE TABLE events ( id SERIAL PRIMARY KEY, created_at TIMESTAMPTZ DEFAULT NOW(), -- timezone-aware (recommended) local_time TIMESTAMP, -- no timezone epoch_time BIGINT -- raw Unix timestamp ); -- Convert between formats SELECT EXTRACT(EPOCH FROM NOW()); -- current Unix timestamp SELECT TO_TIMESTAMP(1738368000); -- '2026-02-01 00:00:00+00' SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2026-02-01T00:00:00Z');

PostgreSQL's TIMESTAMPTZ (timestamp with time zone) is strongly recommended by the PostgreSQL documentation. It stores values in UTC internally and converts to the client's timezone on display, preventing a whole class of timezone-related bugs.

Timestamps in APIs & Web Development

Timestamps are the backbone of time representation in web APIs. Most modern REST and GraphQL APIs use one of two formats for dates:

🔢 Unix Timestamps

Used by: Stripe, Slack, many internal APIs. Compact and unambiguous. Ideal for machine-to-machine communication.

"created": 1738368000

📅 ISO 8601 Strings

Used by: GitHub, Twitter/X, Google APIs. Human-readable and self-documenting. Ideal when responses are read by developers.

"created_at": "2026-02-01T00:00:00Z"

Regardless of which format an API uses externally, the internal storage should always use a consistent, timezone-aware representation. Here are best practices for handling timestamps in web applications:

  • Store in UTC: Always store timestamps in UTC on the server side. Never store local times.
  • Convert on the client: Let the user's browser or app convert UTC to their local timezone for display.
  • Use consistent formats: Pick one format (Unix or ISO 8601) and use it consistently across your entire API.
  • Document your format: Make it clear in your API docs whether timestamps are in seconds or milliseconds.
  • Include timezone info: If using string formats, always include the UTC offset or "Z" suffix.

Time Zones and UTC Considerations

One of the greatest advantages of Unix timestamps is that they sidestep the complexity of time zones entirely. A Unix timestamp represents an absolute instant in time—the same number means the same moment whether you're in New York, London, or Tokyo. The complexity only arises when converting to or from a local time.

Common Timezone Pitfalls

  • Daylight Saving Time (DST): During DST transitions, local times can repeat (fall back) or be skipped (spring forward). A timestamp avoids this because it never changes—only the local interpretation does.
  • Timezone abbreviations are ambiguous: "CST" can mean Central Standard Time (UTC-6), China Standard Time (UTC+8), or Cuba Standard Time. Always use UTC offsets or IANA timezone names (e.g., "America/Chicago").
  • Server vs client timezone: A server in UTC+0 and a user in UTC-5 will interpret the same timestamp differently when converted to local time. Always be explicit about which timezone you mean.
  • Leap seconds: UTC occasionally adds leap seconds (the most recent was in December 2016). Unix time does not account for leap seconds—each day is assumed to have exactly 86,400 seconds. This means Unix time can differ from UTC by up to a second during leap second events, but this is handled by the OS through "smearing" techniques.

💡 The Golden Rule of Time

Store timestamps in UTC (or as Unix epochs). Convert to local time only at the moment of display to the user. This single rule eliminates the vast majority of timezone-related bugs in software.

Common Timestamp Milestones

Throughout computing history, certain Unix timestamps have been notable for their round numbers or their significance:

Unix Timestamp Date (UTC) Significance
0 Jan 1, 1970 00:00:00 The Unix Epoch — the beginning of Unix time
1,000,000,000 Sep 9, 2001 01:46:40 One billion seconds — celebrated by developers
1,234,567,890 Feb 13, 2009 23:31:30 Sequential digits — "the epoch party"
1,500,000,000 Jul 14, 2017 02:40:00 1.5 billion seconds milestone
1,700,000,000 Nov 14, 2023 22:13:20 1.7 billion seconds milestone
1,800,000,000 Jan 15, 2027 08:00:00 1.8 billion seconds — approaching soon
2,000,000,000 May 18, 2033 03:33:20 Two billion seconds
2,147,483,647 Jan 19, 2038 03:14:07 Maximum 32-bit signed integer — the Y2K38 limit

The Year 2038 Problem (Y2K38) Explained

The Year 2038 problem (often abbreviated Y2K38 or the "Epochalypse") is one of the most well-documented yet still unresolved time-related issues in computing. It is directly caused by the way Unix timestamps are stored in older systems.

What Happens?

Systems that store Unix timestamps as a signed 32-bit integer have a maximum value of 2,147,483,647, which corresponds to January 19, 2038 at 03:14:07 UTC. One second later, the integer overflows. Because the integer is signed, the most significant bit flips from 0 to 1, turning the number negative. Instead of representing 2038, the timestamp wraps around to December 13, 1901 at 20:45:52 UTC.

// The Y2K38 overflow visualized 2,147,483,647 → Jan 19, 2038 03:14:07 UTC ✅ Last valid timestamp 2,147,483,648OVERFLOW! Wraps to -2,147,483,648 -2,147,483,648 → Dec 13, 1901 20:45:52 UTC ❌ Time travel!

🚨 Which Systems Are at Risk?

  • Embedded systems: IoT devices, industrial controllers, automotive ECUs, medical devices with 32-bit processors
  • Legacy databases: Systems using 32-bit INT columns for timestamps
  • Old file formats: tar archives, ext3 filesystem timestamps, some FAT32 implementations
  • 32-bit applications: Software compiled for 32-bit architectures that hasn't been updated
  • Network protocols: NTP (Network Time Protocol) uses a different epoch but similar 32-bit overflow

The Solution

The fix is conceptually simple: use 64-bit integers instead of 32-bit. A signed 64-bit integer can represent dates up to approximately 292 billion years in the future—well beyond the expected lifespan of our solar system. Most modern systems have already made this transition:

  • Linux: 64-bit kernels use 64-bit time_t by default. 32-bit kernel support was added in version 5.6 (2020).
  • Windows: Uses 64-bit __time64_t by default since Visual Studio 2005.
  • macOS: Has used 64-bit time_t since Mac OS X 10.0 (2001).
  • Databases: MySQL's BIGINT and PostgreSQL's BIGINT provide 64-bit storage. PostgreSQL's TIMESTAMPTZ is already Y2K38-safe.
  • JavaScript: Uses 64-bit floating-point numbers, safe until year ~275,760.
  • Python: Uses arbitrary-precision integers, so there is no upper limit.

The real challenge lies in the billions of embedded devices and legacy systems that may never receive updates. IoT devices deployed today with 32-bit processors could still be in operation in 2038, making this a problem that the industry needs to address proactively.

Practical Tips for Working with Timestamps

After years of working with timestamps in production systems, here are the most important guidelines we recommend:

  1. Always use UTC for storage. Store all timestamps as Unix epoch integers or UTC datetime values. Convert to local time only for display purposes.
  2. Know your precision. Some systems use seconds (Unix standard), others use milliseconds (JavaScript, Java), and some use microseconds (Python's time.time() returns sub-second precision). Document which precision your system uses.
  3. Use 64-bit storage. If you're storing raw Unix timestamps in a database, use BIGINT (8 bytes) instead of INT (4 bytes) to avoid the Y2K38 problem.
  4. Validate timestamp ranges. If your application accepts timestamps from external sources, validate that they fall within reasonable bounds. A timestamp of 99999999999 might indicate a millisecond value was passed where seconds were expected.
  5. Use established libraries. Don't write your own date parsing or timezone conversion code. Use well-tested libraries: date-fns or Luxon in JavaScript, dateutil or Arrow in Python, java.time in Java.
  6. Test with edge cases. Test your code with timestamps near DST transitions, at midnight UTC, at the epoch (0), and with negative timestamps if your system supports historical dates.
  7. Prefer ISO 8601 for human-facing formats. When serializing dates as strings (in APIs, logs, or exports), use ISO 8601 format with explicit timezone information.

Convert Timestamps Instantly

Need to quickly convert a Unix timestamp to a human-readable date, or vice versa? Try our free online tool — no sign-up required!

Open Timestamp Converter →

Conclusion

Unix timestamps are one of those foundational concepts that quietly power nearly everything in modern computing. Every time you receive a push notification, query a database, call an API, or check a file's modification date, there's a good chance a Unix timestamp is working behind the scenes.

The system is elegantly simple: count the seconds since an arbitrary starting point, and you have a universal, unambiguous, compact representation of any moment in time. Despite being over 50 years old, the concept remains just as relevant today as it was when Ken Thompson and Dennis Ritchie first implemented it at Bell Labs.

Key takeaways:

  • A Unix timestamp is the number of seconds since January 1, 1970 00:00:00 UTC
  • Timestamps are timezone-independent, compact, and easy to compare
  • JavaScript uses milliseconds; most other languages use seconds
  • ISO 8601 is the standard string format for dates in APIs and data exchange
  • The Y2K38 problem affects 32-bit systems—use 64-bit storage
  • Always store time in UTC and convert to local time only for display
  • Use established date/time libraries instead of rolling your own

Whether you're a backend engineer designing APIs, a frontend developer formatting dates for users, or a data analyst parsing log files, a solid understanding of Unix timestamps will serve you well throughout your career.

P

Written by Paras

We create developer-friendly guides and free tools. Have questions about timestamps or time conversion? Contact us.