# Unix Timestamps: Everything You Need to Know

> A Unix timestamp counts seconds since January 1, 1970 UTC. This guide covers epoch time, seconds vs. milliseconds, timezone handling, and the Y2038 problem.

- URL: https://www.browserutils.dev/blog/unix-timestamps-guide
- Published: 2026-07-13
- Updated: 2026-07-02

---

A Unix timestamp (or epoch time) is the number of seconds that have elapsed since January 1, 1970, 00:00:00 UTC. It is the most universal way to represent a point in time in software, appearing in database records, API responses, log files, [JWT tokens](/blog/jwt-tokens-explained), and file metadata.

Despite their simplicity — just a number — timestamps generate a surprising amount of confusion around timezones, precision, and edge cases. This guide covers everything developers need to know about working with them.

## What Is a Unix Timestamp?

A Unix timestamp (also called epoch time or POSIX time) is the number of seconds that have elapsed since January 1, 1970, 00:00:00 UTC. This moment is called the Unix epoch.

```
March 21, 2026 12:00:00 UTC = 1774008000
```

That is it. One number. No timezone ambiguity, no date format parsing, no locale concerns. This simplicity is why timestamps are the standard for storing and transmitting time values.

Some facts about Unix timestamps:

- They are always in UTC — there is no concept of timezone in the number itself
- Negative timestamps represent dates before January 1, 1970
- The current timestamp is around 1.77 billion (as of early 2026)
- They increment by 1 every second (for second-precision timestamps)

## Seconds vs. Milliseconds

Here is a common gotcha: different systems use different precision.

```
Seconds:      1774008000         (10 digits)
Milliseconds: 1774008000000      (13 digits)
Microseconds: 1774008000000000   (16 digits)
Nanoseconds:  1774008000000000000 (19 digits)
```

**JavaScript** uses milliseconds by default:

```javascript
Date.now();              // 1774008000000 (milliseconds)
Math.floor(Date.now() / 1000); // 1774008000 (seconds)
```

**Python** uses seconds (as a float):

```python
import time
time.time()    # 1774008000.123456 (seconds with microsecond precision)
int(time.time())  # 1774008000
```

**Unix command line** uses seconds:

```bash
date +%s     # 1774008000
```

**Databases** vary:
- PostgreSQL `EXTRACT(EPOCH FROM timestamp)` returns seconds as a decimal
- MySQL `UNIX_TIMESTAMP()` returns seconds as an integer
- MongoDB stores dates internally as milliseconds since epoch

When you see a timestamp, count the digits. 10 digits = seconds. 13 digits = milliseconds. Getting this wrong causes dates in the year 58,000 or January 1970. If you need to convert between the two quickly, our [Epoch Milliseconds Converter](/tools/epoch-millis-converter) handles both directions and auto-detects which precision you pasted in.

## Converting Timestamps

### JavaScript

```javascript
// Timestamp to Date
const date = new Date(1774008000 * 1000); // seconds to ms
console.log(date.toISOString()); // "2026-03-21T12:00:00.000Z"

// Date to timestamp
const timestamp = Math.floor(new Date("2026-03-21T12:00:00Z").getTime() / 1000);
// 1774008000

// Current timestamp (seconds)
const now = Math.floor(Date.now() / 1000);
```

### Python

```python
from datetime import datetime, timezone

# Timestamp to datetime
dt = datetime.fromtimestamp(1774008000, tz=timezone.utc)
print(dt.isoformat())  # "2026-03-21T12:00:00+00:00"

# Datetime to timestamp
ts = int(datetime(2026, 3, 21, 12, 0, 0, tzinfo=timezone.utc).timestamp())
# 1774008000
```

### Go

```go
import "time"

// Timestamp to Time
t := time.Unix(1774008000, 0)
fmt.Println(t.UTC().Format(time.RFC3339)) // "2026-03-21T12:00:00Z"

// Time to timestamp
ts := time.Date(2026, 3, 21, 12, 0, 0, 0, time.UTC).Unix()
// 1774008000
```

### SQL (PostgreSQL)

```sql
-- Timestamp to human-readable
SELECT to_timestamp(1774008000) AT TIME ZONE 'UTC';
-- 2026-03-21 12:00:00

-- Current timestamp
SELECT EXTRACT(EPOCH FROM NOW())::integer;
```

## Timezone Handling

The most important rule: **Unix timestamps are always UTC.** A timestamp of 1774008000 means the same instant everywhere in the world. The confusion arises when converting to and from local times.

```javascript
// This timestamp represents 12:00 UTC
const ts = 1774008000;

// Converting without timezone awareness:
const date = new Date(ts * 1000);
console.log(date.toString());
// If your system is in EST: "Sat Mar 21 2026 08:00:00 GMT-0400"
// If your system is in JST: "Sat Mar 21 2026 21:00:00 GMT+0900"

// Same instant, different wall-clock times
console.log(date.toUTCString());
// "Sat, 21 Mar 2026 12:00:00 GMT" — always the same
```

### Common Timezone Mistakes

**Storing local time as a timestamp:** If you convert "March 21, 2026 12:00:00" to a timestamp without specifying a timezone, most languages assume the system's local timezone. The resulting timestamp will be wrong for users in other timezones.

```python
# WRONG: assumes local timezone
datetime(2026, 3, 21, 12, 0, 0).timestamp()

# RIGHT: explicitly UTC
datetime(2026, 3, 21, 12, 0, 0, tzinfo=timezone.utc).timestamp()
```

**Displaying without timezone conversion:** When showing a timestamp to users, always convert to their local timezone. Showing UTC to a user in Tokyo means they need to mentally add 9 hours.

**Ignoring DST:** Daylight Saving Time affects local time display. A timestamp from summer and a timestamp from winter may both be "3:00 PM local" — but they are different UTC times. Always store UTC and convert for display.

To check how a given timestamp maps to different regions without writing code, our [Timezone Converter](/tools/timezone-converter) shows the same instant across multiple timezones side by side.

## The Y2038 Problem

Unix timestamps stored as 32-bit signed integers overflow on January 19, 2038, at 03:14:07 UTC:

```
Maximum 32-bit signed integer: 2,147,483,647
Corresponds to: 2038-01-19 03:14:07 UTC
```

After this moment, a 32-bit timestamp wraps around to negative values, representing dates in December 1901.

**Should you worry?** It depends:

- **64-bit systems:** Modern operating systems and languages use 64-bit timestamps by default, which overflow in about 292 billion years. If your system is 64-bit (and it almost certainly is), you are fine.
- **Databases:** Most databases handle this correctly with 64-bit storage.
- **Embedded systems:** IoT devices, firmware, and 32-bit microcontrollers may still use 32-bit timestamps. This is where Y2038 is a real concern.
- **File formats and protocols:** Some binary formats hardcode 32-bit timestamp fields. Check any format you serialize timestamps into.

## Leap Seconds

UTC occasionally adds a leap second to account for irregularities in Earth's rotation. Unix timestamps do not account for leap seconds — they assume every day has exactly 86,400 seconds.

In practice, this means a Unix timestamp might be off by up to a few seconds from true astronomical time. For virtually all applications, this does not matter. If you are building software for astronomical observation or GPS systems, you need to handle leap seconds explicitly.

As of 2026, there is an ongoing international effort to potentially eliminate leap seconds from UTC by 2035.

## Practical Tips

### Comparing Timestamps

Timestamps make comparison trivial — they are just numbers:

```javascript
const created = 1774008000;
const now = Math.floor(Date.now() / 1000);

// Is it more than 24 hours old?
if (now - created > 86400) {
  console.log("More than a day old");
}

// Time until expiration
const expiresAt = 1774094400;
const secondsRemaining = expiresAt - now;
```

### Storing Timestamps

- **In databases:** Use native timestamp/datetime types when possible. They handle storage, indexing, and timezone conversion more reliably than integer columns.
- **In APIs:** Return timestamps as integers (seconds or milliseconds) or ISO 8601 strings. Document which one you use.
- **In JSON:** There is no standard. ISO 8601 strings (`"2026-03-21T12:00:00Z"`) are human-readable but require parsing. Integer timestamps are smaller and comparison-friendly. Our [ISO 8601 Converter](/tools/iso-8601-converter) converts between the two formats if you need to switch.

### Debugging Timestamps

When troubleshooting time-related issues, you frequently need to convert between timestamps and human-readable dates. Our [Unix Timestamp Converter](/tools/unix-timestamp-converter) handles conversions in both directions — paste a timestamp to see the date, or enter a date to get the timestamp. It auto-detects seconds vs. milliseconds precision and shows the time in multiple formats and timezones simultaneously.

## Quick Reference

| Timestamp | Date |
|-----------|------|
| 0 | 1970-01-01 00:00:00 UTC |
| 946684800 | 2000-01-01 00:00:00 UTC |
| 1000000000 | 2001-09-09 01:46:40 UTC |
| 1700000000 | 2023-11-14 22:13:20 UTC |
| 2000000000 | 2033-05-18 03:33:20 UTC |
| 2147483647 | 2038-01-19 03:14:07 UTC (32-bit max) |

Unix timestamps are beautifully simple: one number, one meaning, no ambiguity. The complexity comes from converting to and from the messy world of timezones, calendars, and human expectations. Keep your stored values in UTC, convert only at the display layer, and always document whether your timestamps are in seconds or milliseconds.