Convert a Unix epoch to a human-readable date
Render a Unix-epoch integer (e.g. `1747396980`) as a readable date — for log inspection, file-metadata audits, and translating database timestamps.
How to convert a unix epoch to a human-readable date in each shell
Bashunix
date -d @1747396980GNU only. `date -d @EPOCH` interprets the integer as Unix seconds; without the leading `@` it tries to parse as a date string. With format: `date -ud @1747396980 +%Y-%m-%dT%H:%M:%SZ`.
Zshunix
date -d @1747396980Fishunix
date -d @1747396980PowerShellwindows
[DateTimeOffset]::FromUnixTimeSeconds(1747396980).UtcDateTime`.UtcDateTime` keeps it in UTC. Drop the `.UtcDateTime` to keep a `[DateTimeOffset]` with offset 0. For ms-precision input: `[DateTimeOffset]::FromUnixTimeMilliseconds(1747396980123)`.
cmd.exewindows
powershell -NoProfile -Command "[DateTimeOffset]::FromUnixTimeSeconds(1747396980).UtcDateTime"cmd has no epoch arithmetic — `(date | time)` math is locale-formatted strings, not integers. Always shell out to pwsh.
Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.
Gotchas & notes
- **GNU vs BSD divergence — different flag entirely**: GNU (Linux) uses `date -d @EPOCH` (the `-d` is "describe a date string"; `@N` is the epoch-string syntax). BSD / macOS uses `date -r EPOCH` (the `-r` is "use the file's mtime, but if it parses as an integer treat as epoch"). These are NOT compatible — `date -d @1747396980` errors on macOS (`date: illegal option -- d`), and `date -r 1747396980` errors on Linux (`date: cannot stat ‘1747396980’: No such file or directory`). Detect the platform first: `if [ "$(uname)" = "Darwin" ]; then date -r $epoch; else date -d @$epoch; fi`. Or install GNU coreutils on macOS (`brew install coreutils`) and use `gdate -d @$epoch`.
- Epoch precision: bash/`date` operates on **seconds**. Milliseconds (JavaScript / Java conventions) require dividing first: `date -d @$((EPOCH_MS / 1000))`. Microseconds (Postgres `epoch_us`) divide by 1,000,000. pwsh has explicit cmdlets for each: `FromUnixTimeSeconds`, `FromUnixTimeMilliseconds` — no `FromUnixTimeMicroseconds`, but `[DateTimeOffset]::UnixEpoch.AddTicks(MICROSECONDS * 10)` works (a tick is 100 ns, so a microsecond is 10 ticks). For nanoseconds (Linux kernel CLOCK_REALTIME, Go `time.UnixNano`), pwsh: `[DateTimeOffset]::UnixEpoch.AddTicks(NS / 100)`.
- pwsh `[DateTimeOffset]::FromUnixTimeSeconds` returns a `[DateTimeOffset]` with offset `+00:00` (UTC); the `.UtcDateTime` accessor unwraps to a `[DateTime]` with `Kind=Utc`. To convert to LOCAL display: `.LocalDateTime` or `.ToLocalTime()`. Common pitfall: `[DateTime]::Parse((Get-Date).ToString())` LOSES the `Kind` — round-trip via `[DateTimeOffset]` or via the `"o"` format specifier instead. For pwsh 5.1 / .NET Framework 4.5 compat: `[DateTimeOffset]::FromUnixTimeSeconds` exists since .NET 4.6 — earlier 4.5 needs manual `(New-Object DateTime 1970,1,1,0,0,0,([DateTimeKind]::Utc)).AddSeconds($epoch)`.
- Reverse direction (date → epoch): GNU `date -d "2026-05-16T14:23:00Z" +%s` (or whatever ISO subset). BSD: `date -j -f "%Y-%m-%dT%H:%M:%SZ" "2026-05-16T14:23:00Z" +%s` — note `-j` ("don't actually set the system clock") and `-f` ("input format"). pwsh: `([DateTimeOffset]"2026-05-16T14:23:00Z").ToUnixTimeSeconds()`. The asymmetry between GNU `-d` and BSD `-j -f` trips up nearly every cross-platform script — putting both branches behind a `to_epoch()` shell function is the durable fix.
Related commands
Related tasks
- Format the current date as ISO 8601— Emit `YYYY-MM-DDTHH:MM:SS±HH:MM` (or the UTC `…Z` form) — the format every machine-readable log, JSON API, and database column should agree on.
- Get the current timestamp— Print the current date / time as either a Unix epoch (seconds since 1970-01-01 UTC) or an ISO 8601 string — for log lines, filenames, expiry calculations, and HTTP `Date` headers.
- Get the current time in UTC— Print the current wall-clock time in UTC (not local time) — essential for log correlation across machines and any DST-safe scheduling logic.
- Parse an ISO 8601 date string— Take a string like `2026-05-16T14:23:00Z` and convert it to a typed date object — for filtering logs by time, computing age, or feeding into date arithmetic.