Learning Hub

Timestamp Tutorials

Learn everything about UNIX timestamps, UTC, and time formats

1

What is a UNIX Timestamp?

A UNIX timestamp (also known as Epoch time or POSIX time) is the number of milliseconds that have elapsed since January 1, 1970 00:00:00 UTC.

It is the universal standard for tracking time in computing — compact, timezone-independent, and easy to compare.

0 ms — Thu Jan 01 1970 00:00:00 UTC
The UNIX Epoch — where it all begins. All timestamps are counted from this moment.
1,000,000,000,000 ms — Sep 9, 2001 01:46:40 UTC
1 trillion milliseconds — a milestone celebrated in the developer community.
1,700,000,000,000 ms — Nov 14, 2023 22:13:20 UTC
1.7 trillion milliseconds — a recent milestone.
2,147,483,647,000 ms — Jan 19, 2038 03:14:07 UTC
The "Year 2038 Problem" — where signed 32-bit integers overflow. Use 64-bit integers to avoid this.
Why milliseconds and not seconds?

The original UNIX standard measured time in seconds. Modern languages (JavaScript, Java) use milliseconds to achieve sub-second precision without floating-point arithmetic. Some systems (Linux clock_gettime, Go's time.Now().UnixNano()) go further with nanoseconds. Always check your language's default unit when working with timestamps.

What makes timestamps universal?
  • No timezone ambiguity — always relative to UTC
  • Single integer — easy to store, compare, and transmit
  • Naturally sortable — larger value = later time
  • No DST conversion ambiguity — wall clock times can be ambiguous, timestamps never are
2

System.currentTimeMillis() in Java

System.currentTimeMillis() is Java's built-in method that returns the current time as the number of milliseconds since January 1, 1970 UTC. It is the Java equivalent of JavaScript's Date.now().

Java
public class TimestampExample {
    public static void main(String[] args) {
        // Get current time in milliseconds
        long millis = System.currentTimeMillis();
        System.out.println("Millis: " + millis);

        // Convert to Date
        java.util.Date date = new java.util.Date(millis);
        System.out.println("Date:   " + date);

        // Modern API (Java 8+) — recommended
        java.time.Instant instant = java.time.Instant.ofEpochMilli(millis);
        System.out.println("Instant: " + instant);
    }
}
Modern Java time API (recommended for Java 8+)

Java 8 introduced the java.time package which is vastly superior to the legacy Date/Calendar API.

import java.time.*;

// Current timestamp in milliseconds
long ms = Instant.now().toEpochMilli();

// Current timestamp in seconds
long sec = Instant.now().getEpochSecond();

// Convert millis back to Instant
Instant instant = Instant.ofEpochMilli(ms);

// Format as ISO 8601
String iso = instant.toString(); // "2026-03-16T10:30:00Z"

// Format with timezone
ZonedDateTime zdt = instant.atZone(ZoneId.of("America/New_York"));
String formatted = zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME);
System.nanoTime() vs currentTimeMillis()

System.nanoTime() returns nanoseconds elapsed since an arbitrary origin — it is not anchored to the UNIX epoch. Use it only for measuring elapsed time, not for wall-clock timestamps.

// Measure elapsed time (correct)
long start = System.nanoTime();
doSomething();
long elapsed = System.nanoTime() - start;
System.out.printf("Took %.2f ms%n", elapsed / 1_000_000.0);

// Wall clock (correct)
long now = System.currentTimeMillis();
💡
Best practice: Prefer Instant.now().toEpochMilli() from java.time for new code. It is immutable, thread-safe, and more expressive than System.currentTimeMillis().
3

Understanding UTC

UTC (Coordinated Universal Time) is the primary time standard by which the world regulates clocks and time. It is the successor to Greenwich Mean Time (GMT) and is the foundation for all UNIX timestamps.

UTC vs GMT — What is the difference?

GMT (Greenwich Mean Time) is the original timezone based on mean solar time at the Royal Observatory in Greenwich, London. UTC is the modern standard based on atomic clocks. They share the same offset (UTC+0 = GMT+0), but UTC is more precise — it incorporates leap seconds to account for irregularities in Earth's rotation.

  • In programming, UTC and GMT are interchangeable. Most databases, APIs, and systems store time in UTC.
  • Leap seconds are added to UTC periodically (since 1972) — most computer systems "smear" or ignore them and do not expose them to application code.
Why store everything in UTC?
  • Timezone rules change (governments adjust DST schedules). UTC never changes.
  • Comparing timestamps across timezones is trivial — just compare UTC values directly.
  • Daylight Saving Time (DST) transitions create ambiguous wall-clock times. UTC has no ambiguity.
  • Databases (PostgreSQL, MySQL) with TIMESTAMP WITH TIME ZONE store values in UTC internally.
ℹ️
Rule: Store all timestamps in UTC. Only convert to local time when displaying to the user.
Getting UTC time in different languages
JavaScript
const now = new Date();
console.log(now.toUTCString());   // "Mon, 16 Mar 2026 10:30:00 GMT"
console.log(now.toISOString());  // "2026-03-16T10:30:00.000Z"
console.log(Date.now());         // ms since epoch (always UTC)
Python
from datetime import datetime, timezone

# UTC-aware datetime
now_utc = datetime.now(timezone.utc)
print(now_utc.isoformat())  # "2026-03-16T10:30:00+00:00"

# Unix timestamp (seconds)
import time
ts = time.time()  # float seconds
4

Working with Timezones

Timezones are one of the most common sources of bugs in software. Understanding how they work — especially Daylight Saving Time (DST) — saves hours of debugging.

Timezone offsets — how they work

A timezone is a region that observes a uniform standard time. Offsets are expressed as UTC+HH:MM or UTC-HH:MM relative to Coordinated Universal Time.

  • UTC+05:30 = India Standard Time (IST) — 5 hours 30 minutes ahead of UTC
  • UTC-05:00 = Eastern Standard Time (EST)
  • UTC+09:00 = Japan Standard Time (JST) — no DST
⚠️
Warning: Never hardcode timezone offsets like +05:30. Use IANA timezone names (e.g. "Asia/Kolkata") because offsets can change due to political decisions.
Daylight Saving Time (DST) explained

DST is the practice of advancing clocks by 1 hour during summer months to extend evening daylight. It is observed in many (but not all) countries.

Common DST pitfalls:

  • Clocks "spring forward" — 2:00 AM becomes 3:00 AM. The 2–3 AM hour does not exist.
  • Clocks "fall back" — 2:00 AM becomes 1:00 AM again. The 1–2 AM hour occurs twice.
  • Events scheduled at ambiguous times may be mis-scheduled by exactly 1 hour.
JavaScript — Safe timezone conversion
// Safe: use Intl.DateTimeFormat with IANA timezone name
const now = new Date();
const fmt = new Intl.DateTimeFormat('en-US', {
  timeZone: 'America/New_York',
  dateStyle: 'full',
  timeStyle: 'long'
});
console.log(fmt.format(now));
// "Monday, March 16, 2026 at 6:30:00 AM EDT"
Countries that do NOT observe DST

Many countries near the equator and some others do not observe DST, making their offset fixed year-round:

  • Japan (UTC+9), China (UTC+8), India (UTC+5:30)
  • Most of Africa, Southeast Asia, and the Middle East
  • Arizona (USA), Hawaii (USA) — state-level exceptions within DST-observing countries
Common timezone traps in code
  1. Parsing dates without a timezonenew Date("2026-03-16") in JavaScript is parsed as UTC midnight, but new Date("03/16/2026") is parsed as local midnight. Always specify timezone explicitly.
  2. Storing local time in the database — always store UTC, convert on output.
  3. Comparing timestamps across DST boundaries — always convert to UTC first.
  4. Scheduling recurring events — use IANA names, not offsets, so future DST transitions are handled automatically.
JavaScript — Parsing pitfall
// DANGER: Different parsing behavior!
new Date("2026-03-16").toISOString();
// "2026-03-16T00:00:00.000Z" — UTC midnight ✓

new Date("03/16/2026").toISOString();
// "2026-03-16T05:00:00.000Z" — local midnight in UTC-5 !

// SAFE: always append time and Z for UTC
new Date("2026-03-16T00:00:00Z").toISOString();
// "2026-03-16T00:00:00.000Z" ✓
5

Timestamp Formats Explained

Many standards define how to write a timestamp as a human-readable string. Choosing the right format depends on your use case.

Format Example Best For
ISO 8601 Recommended 2026-03-16T10:30:00.000Z APIs, databases, log files, JSON payloads
RFC 3339 2026-03-16T10:30:00+00:00 Internet protocols, ATOM feeds — a strict profile of ISO 8601
RFC 2616 (HTTP) Mon, 16 Mar 2026 10:30:00 GMT HTTP headers (Last-Modified, Expires, Cookie)
Unix (seconds) 1773835800 Storage, comparison, arithmetic — smallest representation
Unix (milliseconds) 1773835800000 JavaScript, Java, sub-second precision
Julian Date 2461110.9375 Astronomy, scientific calculations — days since Jan 1, 4713 BC
ISO 8601 in depth

ISO 8601 is the international standard for date and time representation. Key components:

   2026  - 03  - 16  T  10 : 30 : 00 . 000  Z
   Year   Month  Day    Hr   Min  Sec  Ms   UTC

With offset:
   2026-03-16T10:30:00.000+07:00   (UTC+7)
   2026-03-16T10:30:00.000-05:00   (UTC-5)

Date only:
   2026-03-16

Week notation:
   2026-W12-1   (Year-Week-Weekday)
Julian Date calculation

Julian Date (JD) is a continuous count of days since the beginning of the Julian Period (January 1, 4713 BC). The formula from a Unix timestamp (milliseconds) is:

// Julian Date from Unix milliseconds
julianDate = (unixMs / 86400000) + 2440587.5;

// Example: Jan 1, 1970 00:00:00 UTC
// (0 / 86400000) + 2440587.5 = 2440587.5

// JavaScript
const jd = (Date.now() / 86400000) + 2440587.5;
6

Common Timestamp Operations

Since timestamps are just numbers, arithmetic is straightforward. Here are the most common operations:

Adding / Subtracting time
JavaScript
const now = Date.now(); // ms

// Constants (in milliseconds)
const SECOND = 1000;
const MINUTE = 60 * SECOND;
const HOUR   = 60 * MINUTE;
const DAY    = 24 * HOUR;
const WEEK   = 7  * DAY;

// Add 30 days
const in30Days = now + (30 * DAY);

// Subtract 2 hours
const twoHoursAgo = now - (2 * HOUR);

// Add 1 year (approximate — use date lib for exact)
const inOneYear = now + (365.25 * DAY);
⚠️
Adding 30 * DAY always equals exactly 30 UTC days. However, if you need "1 calendar month from now", use a date library (date-fns, Luxon, Day.js) because months have variable lengths.
Comparing timestamps
const ts1 = 1700000000000;
const ts2 = 1773835800000;

// Is ts1 before ts2?
ts1 < ts2; // true

// Difference in days
const diffDays = (ts2 - ts1) / (1000 * 60 * 60 * 24);

// Is a timestamp in the past?
const isExpired = ts1 < Date.now();

// Sort array of timestamps (ascending)
const sorted = [ts2, ts1, 1000000000000].sort((a, b) => a - b);
Date arithmetic — start/end of day, week, month
JavaScript
// Start of today (UTC midnight)
const now = new Date();
const startOfDay = new Date(
  Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())
).getTime();

// Start of this month
const startOfMonth = new Date(
  Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1)
).getTime();

// End of today (last ms)
const endOfDay = startOfDay + (24 * 60 * 60 * 1000) - 1;
Relative time formatting ("2 hours ago")
JavaScript
function relativeTime(ms) {
  const diff = ms - Date.now();
  const abs  = Math.abs(diff);
  const rtf  = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });

  if (abs < 60000)   return rtf.format(Math.round(diff/1000),   'second');
  if (abs < 3600000)  return rtf.format(Math.round(diff/60000),  'minute');
  if (abs < 86400000)  return rtf.format(Math.round(diff/3600000), 'hour');
  return rtf.format(Math.round(diff/86400000), 'day');
}

relativeTime(Date.now() - 7200000); // "2 hours ago"
relativeTime(Date.now() + 86400000); // "tomorrow"
7

Language Quick Reference

How to get the current time as milliseconds since the UNIX epoch in 30+ programming languages.

Language Code Unit
JavaScriptDate.now()ms
TypeScriptDate.now()ms
JavaSystem.currentTimeMillis()ms
KotlinSystem.currentTimeMillis()ms
Pythonint(time.time() * 1000)ms (from s)
C#DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()ms
Gotime.Now().UnixMilli()ms
RustSystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis()ms
PHPround(microtime(true) * 1000)ms (from s)
RubyTime.now.to_i * 1000ms (from s)
SwiftInt(Date().timeIntervalSince1970 * 1000)ms
Objective-C[[NSDate date] timeIntervalSince1970] * 1000ms
C (POSIX)clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec*1000 + ts.tv_nsec/1e6ms
C++chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count()ms
ScalaSystem.currentTimeMillis()ms
GroovySystem.currentTimeMillis()ms
Perlint(time() * 1000)ms (approx)
Luaos.time() * 1000ms (approx)
Ras.numeric(Sys.time()) * 1000ms
MATLABposixtime(datetime('now','TimeZone','UTC')) * 1000ms
Bash / Shelldate +%s%3Nms
PowerShell[DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()ms
SQL (PostgreSQL)EXTRACT(EPOCH FROM NOW()) * 1000ms
SQL (MySQL)UNIX_TIMESTAMP(NOW(3)) * 1000ms
SQL (SQLite)strftime('%s','now') * 1000ms
Dart / FlutterDateTime.now().millisecondsSinceEpochms
Haskellround . (* 1000) <$> getPOSIXTimems
ElixirSystem.system_time(:millisecond)ms
Erlangerlang:system_time(millisecond)ms
Clojure(System/currentTimeMillis)ms
F#DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()ms
Juliaround(Int, time() * 1000)ms
NimgetTime().toUnix() * 1000ms
CrystalTime.utc.to_unix_msms
Zigstd.time.milliTimestamp()ms
Detailed examples for top languages
Python — full example
import time
from datetime import datetime, timezone

# Milliseconds since epoch
ms = int(time.time() * 1000)
print(ms)  # e.g. 1773835800123

# Convert ms back to UTC datetime
dt = datetime.fromtimestamp(ms / 1000, tz=timezone.utc)
print(dt.isoformat())  # "2026-03-16T10:30:00.123000+00:00"
Go — full example
package main

import (
    "fmt"
    "time"
)

func main() {
    // Milliseconds (Go 1.17+)
    ms := time.Now().UnixMilli()
    fmt.Println(ms)

    // Convert back to time.Time
    t := time.UnixMilli(ms)
    fmt.Println(t.UTC().Format(time.RFC3339Nano))
}
C# — full example
using System;

// Milliseconds since epoch
long ms = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
Console.WriteLine(ms);

// Convert back to DateTimeOffset
var dt = DateTimeOffset.FromUnixTimeMilliseconds(ms);
Console.WriteLine(dt.ToString("o")); // ISO 8601
Rust — full example
use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
    let ms = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("Time went backwards")
        .as_millis();

    println!("{}", ms);
}
ℹ️
Need to convert these values interactively? Use the Converter tool to turn any timestamp into a human-readable date instantly.