Skip to content
Back to Blog
Tutorials

Unix Timestamp Guide: Precision, Timezone & DST Best Practices

Learn Unix timestamps: epoch origins, seconds/milliseconds/microseconds conversion, timezone handling, DST pitfalls, and code examples in JavaScript, Python, and Go.

Go Tools Team 14 min read

Unix Timestamp Complete Guide: Seconds/Milliseconds/Microseconds Conversion & Timezone Best Practices

Unix timestamps represent time as “the amount elapsed since the Unix epoch (January 1, 1970, 00:00:00 UTC).” Over 95% of web servers and 90% of database systems globally use this representation internally. This guide covers precision differences, programming language implementations, timezone handling, and daylight saving time considerations.

Unix Timestamp Origins and Definition

The Unix Epoch began on January 1, 1970, 00:00:00 UTC. Unix timestamp 0 corresponds to this moment, while 1262304000 represents 2010-01-01 00:00:00 UTC. The system ignores the effects of leap seconds by default.

Originally stored as 32-bit signed integers, this created the Year 2038 Problem — the maximum value overflows on January 19, 2038, 03:14:07 UTC. Modern systems use 64-bit integers, extending representable timeframes significantly.

Time Precision Differences

UnitCount per SecondDigitsTypical Applications
Seconds (s)110Traditional Unix/Linux systems
Milliseconds (ms)1,00013JavaScript, Java, logging
Microseconds (μs)1,000,00016Distributed tracing, databases
Nanoseconds (ns)1,000,000,00019Go language, performance analysis

Practical rule: 10-digit timestamps generally represent seconds, 13 digits represent milliseconds, 16 digits represent microseconds, and 19 digits represent nanoseconds.

JavaScript Timestamps

JavaScript uses milliseconds natively. The Date() constructor assumes input numbers are milliseconds — for second-level timestamps, multiply by 1000.

// Get current Unix timestamp (in milliseconds)
const timestampMs = Date.now();
console.log(timestampMs);  // Example output: 1692268800123

// For second-level timestamps, divide milliseconds by 1000 and round down
const timestampSec = Math.floor(Date.now() / 1000);
console.log(timestampSec); // Example output: 1692268800

// Convert Unix timestamp back to Date object
let ts = 1692268800;
let date = new Date(ts * 1000);
console.log(date.toISOString()); // "2023-08-17T16:00:00.000Z"

Python Timestamps

Python’s time.time() returns second-level Unix timestamps as floating-point values:

import time
from datetime import datetime, timezone

# Get current Unix timestamp (seconds, float)
now_sec = time.time()
print(now_sec)  # Example output: 1692268800.123456

# Get milliseconds (integer)
now_millis = int(time.time() * 1000)
print(now_millis)  # Example: 1692268800123

# Get nanoseconds (Python 3.7+)
now_nanos = time.time_ns()
print(now_nanos)  # Example: 1692268800123456789

# Convert to datetime
ts = 1692268800
dt_local = datetime.fromtimestamp(ts)
dt_utc = datetime.fromtimestamp(ts, timezone.utc)
print(dt_local.strftime("%Y-%m-%d %H:%M:%S"))  # Local time
print(dt_utc.strftime("%Y-%m-%d %H:%M:%S"))    # UTC time

Go Language Timestamps

Go’s time library provides multiple precision levels:

package main

import (
    "fmt"
    "time"
)

func main() {
    // Get current Unix timestamp
    sec := time.Now().Unix()        // Seconds
    msec := time.Now().UnixMilli()  // Milliseconds (Go 1.17+)
    nsec := time.Now().UnixNano()   // Nanoseconds

    fmt.Println(sec)   // Example: 1692268800
    fmt.Println(msec)  // Example: 1692268800123
    fmt.Println(nsec)  // Example: 1692268800123456789

    // Convert timestamp to Time object
    t := time.Unix(sec, 0)
    fmt.Println(t.UTC())
    fmt.Println(t)
}

Common Errors and Best Practices

Error Example: Unclear Units

// ✗ Wrong: unclear timestamp unit
const timestamp = 1692268800;
const date = new Date(timestamp); // Error: treated as milliseconds, shows 1970

// ✓ Correct: clearly indicate units
const timestampSec = 1692268800;
const timestampMs = 1692268800000;
const dateFromSec = new Date(timestampSec * 1000);

Field Naming Best Practice

log_entry = {
    "timestamp_ms": 1692268800123,           # Millisecond-level
    "timestamp_iso": "2023-08-17T16:00:00Z", # ISO 8601 UTC
    "event_type": "user_login",
    "user_id": 12345
}

Timezone Handling Pitfalls

There are four main pitfalls when working with timezones:

  1. Confusing local time and UTC time — Unix timestamps are always UTC-based; convert to local only at display time
  2. Not saving timezone information — Creates ambiguity; always store UTC or include offset
  3. Cross-system timezone inconsistencies — All systems should use the same timezone reference (recommend UTC)
  4. Manually calculating DST offsets — Rely on built-in libraries, don’t hardcode

The recommended approach: “Standardized storage, localized display.” Use UTC or Unix timestamps in storage and transmission phases to ensure consistency; format according to user timezone when displaying.

Daylight Saving Time (DST) Issues

DST creates two problematic periods:

  • Skipped time: When DST begins, clocks jump forward. For example, 02:00 jumps directly to 03:00, making 02:30 nonexistent.
  • Repeated time: When DST ends, 01:00–01:59 appears twice, creating ambiguity.

Unix timestamps themselves remain continuous and unaffected by DST, but local time conversions require careful handling.

Best Practices for Logging, Databases, and APIs

Logging Systems

Unify UTC timezone + ISO 8601 format; include millisecond timestamps or microsecond precision when necessary.

Databases

Prefer native calendar types with timezone; use BIGINT for numeric timestamps with clear unit indication in field names (e.g., *_epoch_ms).

APIs

Clearly specify formats and units. External interfaces should use ISO 8601 (readable, includes timezone); internal systems can use numeric timestamps with documented units.

Common Error Scenarios

  • 13-digit parsing failure: Millisecond timestamps fed to second-expecting functions cause overflow. Determine units by digit count first.
  • Format mismatches: Invalid dates, missing timezones, or DST switching points cause parsing errors.
  • Timezone offsets: Whole-hour deviations (±8h) typically indicate unification issues. Recommend using UTC internally.
  • Numerical overflow: 32-bit systems face 2038 limits; prioritize 64-bit integers.

Frequently Asked Questions

Why January 1, 1970?

Unix operating system development began in 1970, and it was a round decade year — easy to remember and calculate. 32-bit integers could represent dates from 1970 to 2038, which was sufficient at the time.

How to identify seconds vs. milliseconds?

Three methods: check digit count (10 digits = seconds, 13 = milliseconds, 16 = microseconds, 19 = nanoseconds), calculate verification by parsing and checking reasonableness, or use online conversion tools.

Does the 2038 problem still matter?

Modern systems using 64-bit integers have largely resolved this. Mainstream programming languages already support 64-bit timestamps. Legacy 32-bit systems and embedded devices may still need attention.

Why does DST cause problems?

Time discontinuity from skipped hours and time repetition from repeated hours create parsing ambiguity. Different systems handle ambiguous times with different strategies. Solution: use UTC internally, convert to local time only at display.

Why do JavaScript and Python timestamps differ?

JavaScript’s Date.now() returns milliseconds (13 digits); Python’s time.time() returns seconds (floating-point with microsecond precision). Conversion requires dividing/multiplying by 1000.

  • Higher precision: Financial trading, IoT, and real-time systems demand nanosecond-level accuracy
  • Distributed synchronization: NTP and PTP protocols improve accuracy
  • Blockchain timestamps: Cryptocurrency requires tamper-resistant, high-precision timestamps
  • Performance optimization: SIMD instructions, memory caching, and parallel processing accelerate conversions

Summary

This comprehensive guide covers Unix timestamp essentials — from epoch origins and multi-precision conversions to cross-language implementations, timezone handling, DST pitfalls, and engineering best practices in logging, databases, and API design. The key takeaway: store in UTC, display in local time, and always be explicit about timestamp units.

Related Articles

View all articles