The Most Common Unix Timestamp Mistakes
Working with Unix timestamps seems simple but harbors subtle traps that catch even experienced developers. Understanding common pitfalls helps you avoid them.
Mistake #1: JavaScript's Millisecond Confusion
The Problem:
JavaScript's Date object and Date.now() use milliseconds since epoch, not seconds. Most other systems use seconds.
The Error:
// Wrong: Treats timestamp as milliseconds
const timestamp = 1704067200; // Actually Jan 1, 2024
const date = new Date(timestamp);
console.log(date); // Shows 1970-01-20 (completely wrong!)
// Correct: Multiply by 1000 to convert seconds to milliseconds
const date = new Date(timestamp * 1000);
console.log(date); // 2024-01-01T00:00:00.000Z
Why It Happens:
JavaScript's Date uses milliseconds for historical reasons. Developers coming from Unix systems (which use seconds) frequently make this mistake.
Prevention:
- Always multiply by 1000 when converting Unix seconds to JavaScript milliseconds
- Use
Math.floor(Date.now() / 1000)to get Unix seconds - Add a comment:
// Milliseconds in JavaScript
Mistake #2: Timezone Confusion
The Problem: Unix timestamps are always UTC. Converting to/from local time is a common source of errors.
The Error:
// Wrong assumption: Date string without timezone is UTC
const dateString = "2024-01-01 12:00:00";
const timestamp = new Date(dateString).getTime() / 1000;
// Actually uses local time, not UTC!
// Correct: Explicitly specify UTC
const timestamp = new Date("2024-01-01T12:00:00Z").getTime() / 1000;
// or
const timestamp = Date.UTC(2024, 0, 1, 12, 0, 0) / 1000;
Real-World Impact:
// In New York (UTC-5)
const timestampWrong = new Date("2024-01-01 12:00:00").getTime() / 1000;
// Interprets as EST: 12:00 EST = 17:00 UTC (wrong!)
// In Tokyo (UTC+9)
// Same code: 12:00 JST = 03:00 UTC (different wrong answer!)
// Correct approach
const timestampCorrect = new Date("2024-01-01T12:00:00Z").getTime() / 1000;
// Always 12:00 UTC regardless of system timezone
Prevention:
- Always use ISO format with 'Z' for UTC:
2024-01-01T12:00:00Z - Be explicit about timezone conversions
- Test in different timezones if working with time-sensitive code
Mistake #3: Month Off-by-One Error
The Problem: Many programming languages (JavaScript, Python, some others) use zero-indexed months.
The Error:
// JavaScript: Months are 0-indexed!
const date = new Date(2024, 0, 1); // Month 0 = January (correct by accident)
const date2 = new Date(2024, 1, 1); // Month 1 = February (not March!)
// Wrong
const date3 = new Date(2024, 3, 1); // Expected April? Actually April (0-indexed!)
// Correct way
const date = new Date(2024, 0, 1); // January (month 0)
const date2 = new Date(2024, 11, 1); // December (month 11)
// Or use ISO format to avoid confusion
const timestamp = new Date("2024-04-01T00:00:00Z").getTime() / 1000;
Python (Different Problem):
from datetime import datetime
# Python uses 1-indexed months (more intuitive)
date = datetime(2024, 1, 1) # January 1st
date = datetime(2024, 4, 1) # April 1st
# But when formatting, easy to make mistakes
timestamp = int(date.timestamp())
# This gives local time, not UTC!
# Correct
timestamp = int(date.replace(tzinfo=timezone.utc).timestamp())
Prevention:
- Use ISO date strings (
YYYY-MM-DD) to avoid month confusion - Check documentation for your language's month indexing
- Use date libraries that handle this automatically
Mistake #4: Assuming Consistent Seconds Per Time Unit
The Problem: Not all minutes have 60 seconds, not all days have 24 hours (leap seconds exist), not all years have the same length.
The Error:
// Wrong: Assumes every year is exactly 365 days
const secondsPerYear = 365 * 24 * 60 * 60; // 31,536,000
const ageInYears = totalSeconds / secondsPerYear;
// Off by ~1 day per 4 years!
// Better: Use date math
function getAgeInYears(birthTimestamp) {
const now = new Date();
const birth = new Date(birthTimestamp * 1000);
let age = now.getFullYear() - birth.getFullYear();
const monthDiff = now.getMonth() - birth.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && now.getDate() < birth.getDate())) {
age--;
}
return age;
}
Real-World Impact:
// Leap year effects
2024 is a leap year: 366 days = 31,622,400 seconds
2025 is not: 365 days = 31,536,000 seconds
Difference: 86,400 seconds (1 full day)
// Using average seconds causes 1-day errors every 4 years
Prevention:
- Use date libraries for human-time calculations
- Use simple Unix arithmetic only for short periods (hours, minutes)
- For years/months, use proper date math
Mistake #5: Epoch Time Misunderstanding
The Problem: Confusion about what "Unix epoch" is or assuming it applies universally.
The Error:
// Wrong: Assuming negative timestamps don't exist
const timestamp = -86400; // Valid! Represents Jan 1, 1970 minus 1 day
console.log(new Date(timestamp * 1000)); // 1969-12-31
// Wrong: Assuming Unix epoch is midnight local time
// Unix epoch is Jan 1, 1970 00:00:00 UTC, not your local midnight
// Wrong: Assuming timestamp 0 is the beginning of "today"
const today = 0; // Nope, this is Jan 1, 1970 in UTC
Prevention:
- Remember: Unix epoch is specifically January 1, 1970, 00:00:00 UTC
- Negative timestamps are valid (pre-1970 dates)
- Timestamp 0 is always the same moment worldwide
Mistake #6: Leap Second Ignoring
The Problem: Unix timestamps don't account for leap seconds. When a leap second occurs, the timestamp "jumps over" that second.
The Error:
// On June 30, 2015, a leap second was added
// The second at 23:59:60 UTC was inserted
// Unix timestamps skip this: ...1435708799, 1435708800, 1435708801...
// (There is no timestamp for the leap second)
// Wrong: Assuming every second has exactly one timestamp
const timestamp1 = 1435708799;
const timestamp2 = 1435708800;
const diff = timestamp2 - timestamp1; // 1 second (correct, but skipped leap second)
Real-World Impact: This affects systems that need nanosecond precision or atomic time. Most applications can ignore it.
Prevention:
- Awareness that leap seconds exist
- Use UTC timestamps (not TAI) if leap seconds matter
- Most applications don't need to worry about this
Mistake #7: String Concatenation Instead of Conversion
The Problem: Treating timestamps as strings instead of numbers.
The Error:
// Wrong
const timestamp = "1704067200";
const futureTime = timestamp + 86400; // "1704067200" + 86400 = "170406720086400"
console.log(futureTime); // String concatenation, not addition!
// Correct
const timestamp = parseInt("1704067200");
const futureTime = timestamp + 86400; // 1704153600
In SQL:
-- Wrong
SELECT timestamp + interval '1 day'
FROM events
WHERE timestamp = "1704067200"; -- String comparison!
-- Correct
SELECT timestamp + INTERVAL '1 day'
FROM events
WHERE timestamp = 1704067200; -- Numeric comparison
Prevention:
- Always parse timestamps as numbers
- Use strict typing in languages that support it
- Be explicit:
parseInt(),float(), etc.
Mistake #8: Sign Confusion
The Problem: Working with timestamps, you might accidentally flip the subtraction order.
The Error:
// Want time until expiration
const expirationTime = 1706745600;
const now = 1704067200;
// Wrong: Negative result (past time)
const timeUntilExpiry = now - expirationTime; // Negative!
// Correct
const timeUntilExpiry = expirationTime - now; // Positive
Prevention:
- Add comments indicating direction: "end - start" not "start - end"
- Check for negative values and handle appropriately
- Use absolute value if direction doesn't matter
Mistake #9: Daylight Saving Time Issues
The Problem: When handling local times, DST transitions cause issues.
The Error:
// During DST transition (2:00 AM becomes 3:00 AM)
// Times become ambiguous
// Don't try to construct times manually during DST transition
// Instead, use strings and let the parser handle it
const date = new Date("2024-03-10T02:30:00-05:00"); // EDT vs EST ambiguous
// Correct: Use library that handles DST
import { DateTime } from "luxon";
const dt = DateTime.fromISO("2024-03-10T02:30:00", { zone: "America/New_York" });
Prevention:
- Always use proper date/time libraries (not manual calculation)
- When possible, work entirely in UTC
- Test code during DST transitions
Mistake #10: Assuming Monotonic Timestamps
The Problem: Assuming that time always moves forward (it doesn't when clocks are adjusted).
The Error:
// Wrong: Assuming this always increases
let lastTimestamp = Date.now() / 1000;
// ... later ...
let currentTimestamp = Date.now() / 1000;
// If system clock is adjusted backward, currentTimestamp < lastTimestamp!
// Better: Check for backward time
if (currentTimestamp < lastTimestamp) {
console.warn("System clock was adjusted backward!");
currentTimestamp = lastTimestamp; // Use last known time
}
Prevention:
- Check for negative time deltas
- Use monotonic clocks if available (
process.hrtime()in Node.js) - Handle time-adjustment scenarios gracefully
Testing Timestamp Code
Create Test Cases:
// Test basic conversion
assert(convertToTimestamp("2024-01-01T00:00:00Z") === 1704067200);
// Test timezone handling
assert(convertToTimestamp("2024-01-01T00:00:00Z") ===
convertToTimestamp("2024-01-01T05:00:00+05:00"));
// Test edge cases
assert(isValidTimestamp(-86400)); // Pre-1970 should be valid
assert(isValidTimestamp(0)); // Epoch is valid
assert(isValidTimestamp(253402300799)); // Year 9999
// Test rounding
assert(calculateAge(birthTimestamp) < 150); // Sanity check
Using the Unix Timestamp Converter for Verification
The Unix Timestamp Converter helps verify your work:
- Convert your calculated timestamp back to a readable date
- Verify the date matches expectations
- Check timezone handling
Example workflow:
Calculate: 1704067200 + 86400
Verify: Convert result to readable format
Expected: Jan 2, 2024
Conclusion: Vigilance Prevents Timestamp Bugs
Timestamp errors are among the most frustrating bugs because they often work 99% of the time, failing only on edge cases (leap years, DST transitions, timezone changes). Understanding these common mistakes—JavaScript milliseconds, timezone confusion, off-by-one errors, and DST effects—helps you write robust time-handling code. Use the Unix Timestamp Converter to verify your calculations, test edge cases thoroughly, and prefer date libraries over manual calculation whenever possible.

