Real Epoch Converter logo realepochconverter
programming guide

Java Unix Timestamp: Instant, System.currentTimeMillis & Zones

Java had the legacy Date/Calendar API, then java.time arrived with a clear split: Instant is the raw epoch, ZonedDateTime is zone-aware, and LocalDateTime is deliberately naive. This guide maps all three onto Unix time.

Get the current Unix timestamp

System.currentTimeMillis() is the fast, JIT-friendly path and returns milliseconds. The java.time way is Instant.now().getEpochSecond() for seconds — but note Instant.now() samples the system clock at a coarser granularity than currentTimeMillis() on many JVMs.

Java
import java.time.Instant;

long ms  = System.currentTimeMillis();       // 1767225600123
long sec = Instant.now().getEpochSecond();   // 1767225600
long ms2 = Instant.now().toEpochMilli();     // milliseconds (coarser clock)

Convert a timestamp to a date

Instant.ofEpochSecond(sec) and Instant.ofEpochMilli(ms) are the canonical entry points. An Instant is UTC by definition. To display it in a zone, attach one: atZone(ZoneId.of("Asia/Kolkata")).

Java
import java.time.*;
import java.time.format.DateTimeFormatter;

Instant utc = Instant.ofEpochSecond(1767225600);
utc.toString();                                  // 2026-01-01T00:00:00Z

ZonedDateTime ist = utc.atZone(ZoneId.of("Asia/Kolkata"));
ist.toString();                                  // 2026-01-01T05:30+05:30[Asia/Kolkata]
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(ist);  // 2026-01-01 05:30:00

Convert a date back to a timestamp

Only types that represent an instant can produce an epoch: ZonedDateTime and OffsetDateTime have toEpochSecond()/toInstant(). A LocalDateTime is naive — it has no epoch until you pin it to a zone with atZone().

Java
ZonedDateTime zdt = ZonedDateTime.of(2026, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
zdt.toEpochSecond();                             // 1767225600

// Naive → zone → epoch (a two-step process by design)
LocalDateTime naive = LocalDateTime.of(2026, 1, 1, 0, 0);
naive.atZone(ZoneOffset.UTC).toEpochSecond();    // 1767225600
naive.atZone(ZoneId.of("Asia/Kolkata")).toEpochSecond();  // 1767220200

Naive vs aware: java.time's explicit split

  • Instant — a point on the UTC timeline. Epoch conversions live here.
  • LocalDateTime — a wall-clock reading with no zone. Deliberately naive; atZone() is the only bridge to an instant.
  • ZonedDateTime / OffsetDateTime — zone-aware; the former knows DST rules, the latter only a fixed offset.
  • Rule: store Instant or OffsetDateTime (UTC), convert to ZonedDateTime only at the display boundary.

Native precision: milliseconds

System.currentTimeMillis() is millisecond resolution. Instant supports nanoseconds in its model, but the default Clock only samples the system clock (typically millisecond or microsecond granularity). For true nanosecond timing, inject Clock.tickNanos() or a monotonic clock — those do not align with the epoch, though.

Common pitfalls

  • Legacy Date: new Date(sec * 1000) works but Date.getTime() is ms — the seconds/ms mix-up survives in old code everywhere.
  • SimpleDateFormat — not thread-safe and default-zone-dependent; use DateTimeFormatter.
  • LocalDateTime in JSON — Jackson/Gson default to local time or fail; serialize Instant instead.
  • Clock injectionInstant.now(clock) is how you make timestamp code testable.

Try it live

Check these values in the epoch converter, or copy the current timestamp from the Java snippet tab on the homepage.

First published · Last reviewed · Maintained and developed by the Real Epoch Converter team · [email protected] · Contact · Methodology

Unix time in every language

JavaScript · Python · PHP · SQL · Go · Java · C# · Rust · C++ · PowerShell

Prefer the point-and-click version? The epoch time converter on the home page handles seconds, milliseconds, and microseconds in any timezone — every snippet on this page produces the same value that tool shows.

Copied