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.
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")).
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().
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
InstantorOffsetDateTime(UTC), convert toZonedDateTimeonly 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 butDate.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
Instantinstead. - Clock injection —
Instant.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
Sources & references
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.