← All posts

Unix Time to Date: Convert Epoch to Time in Code

To convert Unix time to a date, first detect the unit: 10 digits means seconds, 13 means milliseconds, and 16 means microseconds. Decode the value as UTC, then format it in the timezone you need. Use the examples below or the epoch-to-date converter for a quick check.

Unix time to date in one line

Here is the whole task in one example: the Unix timestamp 1700000000 converts to 2023-11-14T22:13:20Z — Tuesday, 14 November 2023 at 22:13:20 UTC. A Unix timestamp counts seconds since 1970-01-01 UTC, so converting it means decoding that count as UTC and formatting it in whatever timezone you need. The only thing that breaks conversions is the unit: a 10-digit value is seconds, 13 digits is milliseconds, 16 digits is microseconds. The table below is the copy-paste one-liner for every language and tool covered in this guide.

Language / toolFunctionUnit expectedUTC by default?
JavaScriptnew Date(s * 1000)millisecondsNo — pass a timeZone option
Pythondatetime.fromtimestamp(s, tz=timezone.utc)secondsOnly if tz is set
JavaInstant.ofEpochSecond(s)secondsYes (Instant is UTC)
C# / .NETDateTimeOffset.FromUnixTimeSeconds(s)secondsYes (UTC offset)
Gotime.Unix(s, 0).UTC()secondsWith .UTC()
PHPgmdate('c', s)secondsYes (gm = UTC)
Shell (GNU)date -u -d @ssecondsYes with -u
SQL (Postgres)TO_TIMESTAMP(s)secondsYes (TIMESTAMPTZ)
Excel / Sheets=A1/86400 + DATE(1970,1,1)secondsn/a (no timezone)

Convert 10-digit Unix seconds

A 10-digit modern Unix timestamp is already in seconds. Pass it directly to Python, PHP, Go, SQL, or Linux date; multiply by 1000 only when the API expects milliseconds.

Convert 13-digit epoch milliseconds

A 13-digit value is usually epoch milliseconds. Use it directly in JavaScript Date, Java Instant.ofEpochMilli, or .NET FromUnixTimeMilliseconds; divide by 1000 for tools that expect seconds.

Convert epoch to UTC

UTC output is the safest debugging baseline. Use a Z-suffixed ISO 8601 string, then apply a local timezone only for user-facing display.

What Unix time to date conversion means

A Unix timestamp is the count of seconds since 1970-01-01 UTC. To convert one to a date you decode it as UTC, then format in any timezone. That's the entire problem in one sentence — the rest of this guide is just the syntax in each language. Every modern programming language ships a built-in function that takes a Unix epoch value and returns a date object; the only thing you must be careful about is whether the language expects seconds (Python, PHP, Linux date), milliseconds (JavaScript Date), or microseconds (PostgreSQL, BigQuery).

The quick conversion rule

Count the digits of your value. A 10-digit number is Unix seconds. A 13-digit number is Unix milliseconds. A 16-digit number is Unix microseconds. The Unix epoch began on 1970-01-01 — so 10-digit values now (in 2026) start with 17 or 18; milliseconds start with 175 or 176 followed by 10 zeros; microseconds start with 1758 or 1759. Detect the unit before you pass the value to any conversion function, and your output will land on the correct day instead of in 1970.

  • 10 digits → Unix seconds (range 2001 to 2286)
  • 13 digits → Unix milliseconds (range 2001 to 2286)
  • 16 digits → Unix microseconds (range 2001 to 2286)
  • Numbers near 10^9 (1,000,000,000) are pre-2001 seconds — still valid Unix time
  • Negative integers are pre-1970 dates — most languages handle them; verify
  • Numbers above 2^31 in INT columns hit the Year 2038 limit — see below

Why epoch-to-date results land in 1970

The 1970 symptom usually means a seconds value was sent to a millisecond API. Check the digit count before changing timezone or date-format code.

When the value is microseconds

A 16-digit value is common in databases and event streams. Divide by 1,000,000 for seconds-based APIs, or use native microsecond helpers such as BigQuery TIMESTAMP_MICROS.

Convert Unix time to a date in JavaScript

JavaScript's Date constructor expects milliseconds, so a Unix-seconds value must be multiplied by 1000 first. The result is a Date object; format it with toISOString() for ISO 8601 UTC, or with Intl.DateTimeFormat for a timezone-aware human-readable string. Always pass an explicit timeZone option — without it, JavaScript uses the runtime's local timezone, which differs between developer laptops and production servers.

  • new Date(1700000000 * 1000).toISOString() // '2023-11-14T22:13:20.000Z'
  • new Date(1700000000 * 1000).toLocaleString('en-US', { timeZone: 'America/New_York' }) // tz-aware
  • new Date(1700000000000).toISOString() // milliseconds — no × 1000 needed
  • new Intl.DateTimeFormat('en-US', { timeZone: 'Asia/Tokyo', dateStyle: 'full', timeStyle: 'long' }).format(new Date(ms))
  • Detect unit at runtime: const toDate = ts => new Date(ts < 1e11 ? ts * 1000 : ts)

Convert Unix time to a date in Python

Python's datetime.fromtimestamp(ts, tz=timezone.utc) is the canonical conversion. The tz argument is required for a UTC result; without it, Python returns the timestamp in the system's local timezone — a frequent source of timezone-drift bugs on servers. utcfromtimestamp() is deprecated as of Python 3.12 because it returned a naive datetime that was easy to misuse. For milliseconds, divide by 1000; for microseconds, divide by 1,000,000 — Python accepts fractional seconds directly.

  • from datetime import datetime, timezone
  • datetime.fromtimestamp(1700000000, tz=timezone.utc) # 2023-11-14 22:13:20+00:00
  • datetime.fromtimestamp(1700000000.123, tz=timezone.utc) # fractional seconds work
  • datetime.fromtimestamp(ms / 1000, tz=timezone.utc) # from milliseconds
  • datetime.fromtimestamp(us / 1_000_000, tz=timezone.utc) # from microseconds
  • Avoid: datetime.utcfromtimestamp(ts) — deprecated in 3.12; returns naive datetime

Convert Unix time to a date in PHP

PHP's gmdate(format, timestamp) returns a UTC date string for the given Unix seconds; date(format, timestamp) returns the same instant in the server's local timezone (controlled by date_default_timezone_set or php.ini). The DateTime class with DateTimeZone gives the modern, immutable API and supports arbitrary IANA timezone names. PHP works in seconds by default, so divide millisecond values by 1000 first.

  • gmdate('c', 1700000000) // '2023-11-14T22:13:20+00:00' (UTC ISO 8601)
  • date('Y-m-d H:i:s', 1700000000) // server-local — depends on date.timezone setting
  • new DateTime('@1700000000') // immutable, UTC by default with the @ prefix
  • (new DateTime('@1700000000'))->setTimezone(new DateTimeZone('Asia/Tokyo'))->format('c')
  • DateTime::createFromFormat('U.u', '1700000000.123456') // sub-second precision

Convert Unix time to a date in Java

Java's java.time API (Java 8+) converts Unix seconds with Instant.ofEpochSecond(s), which returns a UTC instant — Instant is always UTC, so there is no hidden local-timezone surprise. Use Instant.ofEpochMilli(ms) for millisecond input, attach a zone with atZone(ZoneId.of(...)) for a wall-clock rendering, and format with DateTimeFormatter. The legacy java.util.Date constructor expects milliseconds, like JavaScript — multiply seconds by 1000L first.

  • Instant.ofEpochSecond(1700000000) // 2023-11-14T22:13:20Z (UTC)
  • Instant.ofEpochMilli(1700000000000L) // from milliseconds
  • Instant.ofEpochSecond(1700000000).atZone(ZoneId.of("Asia/Tokyo")) // tz-aware
  • DateTimeFormatter.ISO_INSTANT.format(Instant.ofEpochSecond(s)) // ISO 8601
  • new java.util.Date(1700000000L * 1000) // legacy API — expects milliseconds

Convert Unix time to a date in C# (.NET)

In .NET, DateTimeOffset.FromUnixTimeSeconds(s) is the modern conversion — it returns a DateTimeOffset anchored to UTC (+00:00). Use FromUnixTimeMilliseconds(ms) for millisecond input. Read .UtcDateTime for a UTC DateTime, or convert to a specific zone with TimeZoneInfo.ConvertTime. Format with the round-trip "o" specifier for ISO 8601. The built-in Unix methods (added in .NET 4.6) handle the epoch math, so avoid the old DateTime.AddSeconds-from-1970 pattern.

  • DateTimeOffset.FromUnixTimeSeconds(1700000000) // 2023-11-14 22:13:20 +00:00
  • DateTimeOffset.FromUnixTimeMilliseconds(1700000000000) // from milliseconds
  • DateTimeOffset.FromUnixTimeSeconds(s).UtcDateTime // DateTime in UTC
  • TimeZoneInfo.ConvertTime(dto, tzInfo) // tz-aware rendering
  • DateTimeOffset.FromUnixTimeSeconds(s).ToString("o") // ISO 8601 round-trip

Convert Unix time to a date in Go

Go's time.Unix(sec, nsec) builds a Time from Unix seconds plus optional nanoseconds, but it returns the value in the local timezone — call .UTC() to anchor it. Go 1.17 added time.UnixMilli(ms) and time.UnixMicro(us) so you no longer divide by hand. Format with the RFC3339 constant for ISO 8601, and use .In(loc) with time.LoadLocation for a specific zone.

  • time.Unix(1700000000, 0).UTC() // 2023-11-14 22:13:20 +0000 UTC
  • time.UnixMilli(1700000000000).UTC() // from milliseconds (Go 1.17+)
  • time.UnixMicro(1700000000000000).UTC() // from microseconds (Go 1.17+)
  • time.Unix(1700000000, 0).Format(time.RFC3339) // ISO 8601 string
  • time.Unix(s, 0).In(loc) // tz-aware; loc from time.LoadLocation

Convert Unix time to a date in shell (Linux / macOS)

On Linux the GNU date command uses -d @ts to convert from Unix seconds; on macOS the BSD date command uses -r ts for the same job. The flags differ by historical implementation — the actual epoch math is identical. The -u flag forces UTC output regardless of the TZ environment variable. Both implementations support arbitrary output formats via the +%FORMAT argument; the most useful format strings are summarized below.

  • GNU (Linux): date -u -d @1700000000 // 'Tue Nov 14 22:13:20 UTC 2023'
  • GNU: date -u -d @1700000000 +'%Y-%m-%dT%H:%M:%SZ' // ISO 8601 UTC
  • BSD (macOS): date -u -r 1700000000 // same result, different flag
  • BSD: date -u -r 1700000000 +'%Y-%m-%dT%H:%M:%SZ'
  • Both: omit -u to use TZ environment variable; export TZ=America/New_York to override
  • Sub-second: date -u -d @1700000000.123 +'%Y-%m-%dT%H:%M:%S.%3NZ' (GNU only)

Convert Unix time to a date in SQL (Postgres, MySQL, SQLite, BigQuery)

Every major SQL dialect has a built-in function for converting Unix seconds (or milliseconds, or microseconds) to a native timestamp column. The function names vary, but the unit each expects is documented and consistent within a database. Use the dedicated function rather than computing the result manually with date arithmetic — the built-ins handle leap years, sub-second precision, and timezone conversion correctly.

  • PostgreSQL: TO_TIMESTAMP(1700000000) // returns TIMESTAMPTZ
  • PostgreSQL: TO_TIMESTAMP(unix_us / 1000000.0) // for microsecond input
  • MySQL: FROM_UNIXTIME(1700000000) // returns DATETIME in session timezone
  • MySQL: CONVERT_TZ(FROM_UNIXTIME(ts), @@session.time_zone, 'UTC') // force UTC
  • SQLite: datetime(1700000000, 'unixepoch') // returns TEXT 'YYYY-MM-DD HH:MM:SS'
  • SQLite: datetime(ms / 1000, 'unixepoch') // from milliseconds
  • BigQuery: TIMESTAMP_SECONDS(1700000000), TIMESTAMP_MILLIS(ms), TIMESTAMP_MICROS(us)
  • ClickHouse: toDateTime(1700000000), fromUnixTimestamp(1700000000)

Convert Unix time to a date in Excel

Excel stores dates as serial numbers — the count of days since 1900-01-01. Converting a Unix timestamp to an Excel date is just unit conversion: divide the Unix seconds by 86,400 (seconds per day) and add the date 1970-01-01, then format the cell as a date. The formula =A1/86400 + DATE(1970,1,1) is the canonical answer and works in every modern version of Excel. For milliseconds, divide by 86,400,000 instead. After entering the formula, select the cell, open Format Cells (Ctrl+1), and pick a Date format under the Number tab.

  • Seconds: =A1/86400 + DATE(1970,1,1) // when A1 holds the Unix seconds value
  • Milliseconds: =A1/86400000 + DATE(1970,1,1)
  • Microseconds: =A1/86400000000 + DATE(1970,1,1)
  • Format cell as Date after entering the formula (Ctrl+1 → Number → Date)
  • Caveat: Excel's epoch is 1900-01-01, not 1970, hence the + DATE(1970,1,1) offset
  • Reverse direction (date to Unix): =(A1 - DATE(1970,1,1)) * 86400

Convert Unix time to a date in Google Sheets

Google Sheets accepts the same canonical Excel formula and also provides a dedicated EPOCHTODATE function. The shortcut form is =EPOCHTODATE(A1, 1), where the second argument is the unit code: 1 for seconds, 2 for milliseconds, 3 for microseconds. The output is a UTC-anchored date that Sheets renders in the spreadsheet's locale settings. For sheets shared across teams in different timezones, document which timezone the dates are intended to represent in the column header.

  • =EPOCHTODATE(A1, 1) // seconds — shorthand
  • =EPOCHTODATE(A1, 2) // milliseconds
  • =EPOCHTODATE(A1, 3) // microseconds
  • =A1/86400 + DATE(1970,1,1) // canonical formula — works in Sheets too
  • Reverse direction: =(A1 - DATE(1970,1,1)) * 86400
  • Time zone applied is the sheet's locale; check File → Settings → Time zone

UTC date vs local date — which one to display

A Unix timestamp encodes a moment in time, not a wall-clock display. Two visitors in different timezones see the same Unix timestamp as different wall-clock dates. The right behavior depends on what the date represents: event logs and audit records should display in UTC for cross-region comparison; user-facing dates (deadlines, meeting times, expiration notices) should display in the user's local timezone. Always pick one and document it; never store a string that was already converted to local time without also storing the timezone it came from.

  • Server logs → display in UTC, label the column or chart axis explicitly
  • User-facing deadlines → display in the user's timezone (auto-detect via Intl.DateTimeFormat().resolvedOptions().timeZone)
  • Recurring schedules ('every Monday 9 AM Eastern') → store the timezone alongside the rule, recompute the next instant on each fire
  • API responses → ISO 8601 with Z suffix (UTC) is the safe default; let the client convert
  • Database storage → UTC always; convert only at the presentation layer

Use UTC for logs and APIs

In production debugging, UTC is the fastest way to compare the same timestamp across servers, databases, and browser clients without local offset noise.

Use local time for humans

After the UTC check passes, format the same instant in the user's IANA timezone for dashboards, deadlines, and calendar-facing screens.

Edge cases: sub-second precision, negative timestamps, and Year 2038

Three edge cases trip up code that's otherwise correct. Microsecond timestamps (16 digits) need explicit unit handling; treating them as seconds gives a date 1,000,000× too far in the future. Negative Unix timestamps represent dates before 1970 — most languages handle them, but Excel, Google Sheets, and some SQL functions clamp at 1970 or return errors. The Year 2038 problem is the 32-bit signed integer wrap that hits 2038-01-19 03:14:07 UTC; values past that point require BIGINT storage or 64-bit time_t.

  • Microseconds (16 digits) — divide by 1,000,000 before passing to language-level seconds functions
  • Negative seconds — pre-1970 dates; JavaScript Date, Python datetime, PHP DateTime all handle them
  • Negative seconds in Excel — produces #### or a wrong date; use the formula =A1/86400 + DATE(1970,1,1) only for positive values
  • Year 2038 — INT and signed 32-bit time_t overflow at 2147483647 = 2038-01-19 03:14:07 UTC
  • Beyond 2038 — store as BIGINT (signed 64-bit covers 292 billion years either side of epoch)
  • Below 1900 in Excel — the application has no rendering for it; convert to text or upstream BCE-aware library

Common bugs converting Unix time to a date

The same bug shows up every time someone converts Unix time to a date for the first time: the result lands in 1970. The cause is almost always a missed × 1000 in JavaScript, or the missing tz argument in Python, or a numeric column auto-truncated by Excel. The companion bug article catalogs all 10 — every one of them appears in code that converts Unix time at some point. Skim it once and most never make it to production.

  • Date shows 1970 — you passed seconds where milliseconds were expected (JS Date constructor)
  • Date is off by your local UTC offset — you forgot to specify tz=timezone.utc (Python) or timeZone option (JS)
  • Excel shows ##### or a #VALUE! error — the cell isn't formatted as Date, or the value is negative
  • SQL FROM_UNIXTIME returns the wrong wall-clock — MySQL applies @@session.time_zone; force UTC explicitly
  • Server vs laptop produce different dates — different system timezones; always pass tz explicitly

FAQ

How do I get a date from a Unix timestamp?
Identify whether the value is seconds (10 digits) or milliseconds (13 digits), then call your language's built-in conversion: new Date(seconds * 1000) in JavaScript, datetime.fromtimestamp(seconds, tz=timezone.utc) in Python, gmdate('c', seconds) in PHP, or date -u -d @seconds in a shell.
How do I get a date from a Unix timestamp in JavaScript?
Multiply the seconds value by 1000 (JavaScript's Date constructor expects milliseconds), then format with toISOString() or Intl.DateTimeFormat. Example: new Date(1700000000 * 1000).toISOString() returns "2023-11-14T22:13:20.000Z".
How do I get a date from a Unix timestamp in Python?
Use datetime.fromtimestamp(unix_seconds, tz=timezone.utc). The tz argument is required for a UTC result; without it, Python returns the timestamp in the system's local timezone. utcfromtimestamp() is deprecated as of Python 3.12.
How do I convert Unix time to a date?
Pass the value to your language's built-in epoch-to-datetime function with the correct unit (seconds or milliseconds) and a UTC timezone. The result is the same instant in time, formatted as a human-readable date.
Is Linux time the same as Unix time?
Yes. Linux, macOS, and every Unix-derived system use the same epoch base — seconds since 1970-01-01 00:00:00 UTC. The date command, time() syscall, and clock_gettime() all return Unix time.
Why does my Unix timestamp convert to 1970?
Almost always because you passed seconds to a function expecting milliseconds (or 0 / null cast to a number). new Date(1700000000) in JavaScript lands in January 1970 — the constructor expects milliseconds. Multiply by 1000 first.
How do I convert Unix time to a date in Excel?
Use =A1/86400 + DATE(1970,1,1) where A1 holds Unix seconds. Format the result as Date in the Format Cells dialog. For milliseconds, divide by 86400000 first: =A1/86400000 + DATE(1970,1,1).
How do I convert Unix time to a date in Google Sheets?
Same canonical formula as Excel: =A1/86400 + DATE(1970,1,1). Google Sheets also accepts the shorter =EPOCHTODATE(A1, 1) where the second argument is the unit (1 = seconds, 2 = milliseconds, 3 = microseconds).
How do I handle microsecond Unix timestamps (16 digits)?
Divide by 1,000,000 to get seconds, then convert as usual. Python 3.7+ accepts fractional seconds directly: datetime.fromtimestamp(unix_us / 1_000_000, tz=timezone.utc). PostgreSQL TO_TIMESTAMP and BigQuery TIMESTAMP_MICROS handle microseconds natively.
How do I convert epoch to UTC?
Treat the epoch value as Unix seconds unless it has 13 digits, then use a UTC formatter: date -u -d @seconds in Linux, new Date(seconds * 1000).toISOString() in JavaScript, or datetime.fromtimestamp(seconds, tz=timezone.utc) in Python.