Unix Timestamp Guide: Understanding Epoch Time and Timezones
Master Unix timestamps, epoch time, and timezone handling. Learn conversion techniques, common pitfalls, and best practices for working with timestamps across different programming languages.
What is Unix Timestamp?
Unix timestamp (also known as Unix time, POSIX time, or epoch time) is a system for describing a point in time. It represents the number of seconds that have elapsed since 00:00:00 UTC on January 1, 1970 (the Unix epoch).
Key Characteristics:
- Always in UTC (no timezone information)
- Typically stored as a 32-bit or 64-bit integer
- Precision can be seconds or milliseconds
- Platform and language independent
The Epoch
The Unix epoch (00:00:00 UTC on 1 January 1970) was chosen arbitrarily by early Unix engineers. This date is the reference point from which time is measured.
// The epoch in different representations
Timestamp: 0
ISO 8601: 1970-01-01T00:00:00Z
Human readable: Thursday, January 1, 1970 12:00:00 AM UTC
// Current time (example)
Timestamp: 1674567890
ISO 8601: 2023-01-24T12:24:50Z
Human readable: Tuesday, January 24, 2023 12:24:50 PM UTC
Seconds vs Milliseconds
Unix timestamps can be represented in different precisions:
Seconds (Traditional)
10-digit number
1674567890
Milliseconds (JavaScript)
13-digit number
1674567890123
// Converting between precisions
const seconds = 1674567890;
const milliseconds = seconds * 1000; // 1674567890000
// From milliseconds to seconds
const ms = 1674567890123;
const sec = Math.floor(ms / 1000); // 1674567890
Converting Timestamps
// Current timestamp in seconds
const timestamp = Math.floor(Date.now() / 1000);
console.log(timestamp); // e.g., 1674567890
// Timestamp in milliseconds
const timestampMs = Date.now();
console.log(timestampMs); // e.g., 1674567890123
// From specific date
const date = new Date('2024-01-15T10:30:00Z');
const ts = Math.floor(date.getTime() / 1000);
Online Converter Tool
Need to quickly convert timestamps? Try our Unix Timestamp Converter tool for instant conversions with timezone support.
Working with Timezones
Unix timestamps are always in UTC, but when converting to human-readable formats, timezone handling becomes crucial. Understanding how to properly work with timezones prevents common bugs in international applications.
⚠️ Important: Unix timestamps are timezone-agnostic
The same timestamp represents the same moment in time globally. The timezone only matters when displaying the time to users.
Timezone Conversion Examples
// JavaScript timezone handling
const timestamp = 1674567890; // Always UTC
const date = new Date(timestamp * 1000);
// Local timezone (browser/system)
console.log(date.toString());
// Tue Jan 24 2023 07:24:50 GMT-0500 (Eastern Standard Time)
// Specific timezone using Intl.DateTimeFormat
const options = {
timeZone: 'America/New_York',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
};
console.log(new Intl.DateTimeFormat('en-US', options).format(date));
// 01/24/2023, 07:24:50
// Different timezones
const timezones = ['UTC', 'America/Los_Angeles', 'Europe/London', 'Asia/Tokyo'];
timezones.forEach(tz => {
const formatted = new Intl.DateTimeFormat('en-US', {
...options,
timeZone: tz,
timeZoneName: 'short'
}).format(date);
console.log(`${tz}: ${formatted}`);
});
Storing Timestamps
Best Practices:
- ✓ Always store timestamps in UTC
- ✓ Convert to user's timezone only for display
- ✓ Store timezone preference separately if needed
- ✓ Use ISO 8601 format for APIs (2023-01-24T12:24:50Z)
Database Storage
-- PostgreSQL
CREATE TABLE events (
id SERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
-- or store as integer
created_timestamp BIGINT DEFAULT EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)
);
-- MySQL
CREATE TABLE events (
id INT AUTO_INCREMENT PRIMARY KEY,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- or store as integer
created_timestamp INT UNSIGNED DEFAULT UNIX_TIMESTAMP()
);
-- Query with timezone conversion (PostgreSQL)
SELECT
created_at AT TIME ZONE 'America/New_York' as ny_time,
created_at AT TIME ZONE 'UTC' as utc_time
FROM events;
Common Pitfalls and Issues
1. The Year 2038 Problem (Y2K38)
32-bit systems storing Unix timestamps as signed integers will overflow on January 19, 2038, at 03:14:07 UTC.
// Maximum 32-bit signed integer
const MAX_32BIT = 2147483647; // 0x7FFFFFFF
const date = new Date(MAX_32BIT * 1000);
console.log(date.toISOString()); // 2038-01-19T03:14:07.000Z
// Next second causes overflow
const overflow = MAX_32BIT + 1; // Becomes negative in 32-bit systems
Solution: Use 64-bit integers or migrate to 64-bit systems.
2. Leap Seconds
Unix time doesn't account for leap seconds. When a leap second occurs, Unix time either repeats a second or skips it.
// During a leap second (hypothetical)
// 23:59:59 -> 23:59:60 -> 00:00:00
// Unix time might show:
1483228799 // 2016-12-31 23:59:59 UTC
1483228799 // 2016-12-31 23:59:60 UTC (repeated!)
1483228800 // 2017-01-01 00:00:00 UTC
3. Precision Loss
Converting between seconds and milliseconds can cause precision loss if not handled carefully.
// Wrong: Loses millisecond precision
const ms = 1674567890123;
const seconds = parseInt(ms / 1000); // 1674567890
const backToMs = seconds * 1000; // 1674567890000 (lost 123ms!)
// Correct: Preserve precision
const originalMs = 1674567890123;
const seconds = originalMs / 1000; // 1674567890.123
const preservedMs = Math.round(seconds * 1000); // 1674567890123
4. Timezone Assumptions
Never assume the server and client are in the same timezone.
// Bad: Assumes server timezone
const serverTime = new Date().getHours(); // Could be any timezone!
// Good: Always work with UTC
const utcHours = new Date().getUTCHours();
// Better: Send timestamps, let client handle display
const response = {
timestamp: Math.floor(Date.now() / 1000),
timezone: 'UTC' // Be explicit
};
Best Practices
1. Storage and Transmission
- Use UTC everywhere: Store and transmit all timestamps in UTC. Convert to local time only for display.
- Be consistent with precision: Choose either seconds or milliseconds and stick with it throughout your application.
- Document your format: Always document whether your API uses seconds or milliseconds.
2. API Design
// Good API response structure
{
"data": {
"id": "123",
"title": "Event Name",
"created_at": 1674567890, // Unix timestamp
"created_at_iso": "2023-01-24T12:24:50Z", // ISO 8601
"timezone": "UTC" // Be explicit
},
"meta": {
"timestamp_format": "seconds", // Document format
"server_time": 1674567900 // Current server time
}
}
// Support multiple formats in requests
POST /api/events
{
"title": "New Event",
// Accept multiple formats
"scheduled_at": "2023-01-25T10:00:00Z", // ISO 8601
// or
"scheduled_at_timestamp": 1674637200 // Unix timestamp
}
3. Validation and Error Handling
// Timestamp validation
function isValidTimestamp(timestamp, options = {}) {
const {
allowMilliseconds = true,
minYear = 1970,
maxYear = 2100
} = options;
// Check if number
if (typeof timestamp !== 'number' || isNaN(timestamp)) {
return false;
}
// Convert to seconds if milliseconds
const seconds = timestamp > 9999999999
? Math.floor(timestamp / 1000)
: timestamp;
// Check reasonable range
const date = new Date(seconds * 1000);
const year = date.getUTCFullYear();
return year >= minYear && year <= maxYear;
}
// Safe conversion with error handling
function safeTimestampToDate(timestamp) {
try {
if (!isValidTimestamp(timestamp)) {
throw new Error('Invalid timestamp');
}
// Handle both seconds and milliseconds
const ms = timestamp > 9999999999
? timestamp
: timestamp * 1000;
return new Date(ms);
} catch (error) {
console.error('Timestamp conversion failed:', error);
return null;
}
}
4. Testing Timestamps
// Mock timestamps for testing
const FIXED_TIMESTAMP = 1674567890;
// Jest example
beforeEach(() => {
jest.useFakeTimers();
jest.setSystemTime(new Date(FIXED_TIMESTAMP * 1000));
});
afterEach(() => {
jest.useRealTimers();
});
// Test timezone handling
test('displays correct local time', () => {
const timestamp = 1674567890;
const date = new Date(timestamp * 1000);
// Test with specific timezone
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'America/New_York',
dateStyle: 'medium',
timeStyle: 'medium'
});
expect(formatter.format(date)).toBe('Jan 24, 2023, 7:24:50 AM');
});
Quick Reference
Common Timestamp Values
Epoch: 0
One day: 86400
seconds
One week: 604800
seconds
Year 2000: 946684800
Year 2038 limit: 2147483647
Current (approx): ~1700000000