Convert Unix Epoch: The Practical, No‑Fluff Guide
Introduction
If you work with logs, APIs, or databases, you often need to convert Unix epoch into readable dates. Whether the value is in seconds or milliseconds, getting it wrong can shift your time by hours—or even decades. This guide shows you how to convert Unix epoch correctly, across languages and tools, and avoid costly mistakes.
Featured Snippet Answer
To convert Unix epoch to a readable date: 1) Detect the unit (seconds vs. milliseconds). 2) If milliseconds, divide by 1000 for seconds or use millisecond‑aware APIs. 3) Convert in UTC first, then apply the desired time zone. 4) Output in ISO 8601 for consistency. Example: JavaScript new Date(1697040000 * 1000).toISOString(); Python: datetime.utcfromtimestamp(1697040000).isoformat() + "Z".
AI Overview
This guide explains Unix epoch (POSIX time) and how to convert it safely. You’ll learn to detect seconds vs. milliseconds, handle UTC and time zones, format ISO 8601, and convert both directions (date ↔ epoch). It includes code for JavaScript, Python, Bash, PHP, Java, C#, and SQL (PostgreSQL, MySQL, SQLite), plus real examples, common mistakes, best practices, and expert tips. Ideal for developers, analysts, SREs, and data engineers.
Key Takeaways
- Always detect epoch units: seconds, milliseconds, or microseconds.
- Convert in UTC first, then display in a specific time zone.
- Use ISO 8601 (e.g., 2024-03-12T09:00:00Z) for reliable interchange.
- Watch for daylight saving (DST) and locale formatting pitfalls.
- Databases differ: TIMESTAMP vs. TIMESTAMPTZ matters.
- Prefer integers for storage, and document the unit.
- Validate with known test timestamps before shipping.
Table of Contents
- What is "convert Unix epoch"?
- Why It Matters
- Benefits
- Step-by-Step Guide
- Step 1: Know Your Units
- Step 2: Convert in Popular Languages
- Step 3: Handle Time Zones
- Step 4: Format Output (ISO 8601)
- Step 5: Convert Dates Back to Epoch
- Step 6: Validate and Test
- Real World Examples
- Common Mistakes
- Best Practices
- Expert Tips
- Comparison Table
- Frequently Asked Questions
- External References
- Internal Link Suggestions (ZenixTools)
- Conclusion
- Call To Action
What is "convert Unix epoch"?
“Convert Unix epoch” refers to turning a Unix timestamp (also called Unix time or POSIX time) into a human-readable date and time, and vice versa. The Unix epoch starts at 1970‑01‑01T00:00:00Z (UTC). Timestamps are often stored as the number of seconds (or milliseconds) since this moment.
Related terms you’ll see:
- Unix timestamp, epoch time, POSIX time
- Seconds since 1970, milliseconds since 1970
- UTC, ISO 8601, time zone offset
Why It Matters
- Many APIs, logs, and databases store time as integers for speed.
- Conversions are needed for dashboards, reports, alerts, and audits.
- A one-hour time zone error can break SLAs and analytics.
- Seconds vs. milliseconds confusion can shift dates by decades.
Benefits
- Consistent time handling across systems.
- Clear auditing and reproducible analytics.
- Easier cross‑platform debugging and log correlation.
- Better performance and smaller storage in data pipelines.
Step-by-Step Guide
Step 1: Know Your Units
- Seconds (most common): e.g., 1697040000 ≈ 2023‑10‑11T00:00:00Z
- Milliseconds: e.g., 1697040000000 (three extra zeros)
- Microseconds: e.g., 1697040000000000 (six extra zeros)
Heuristics:
- 10 digits ~ seconds (1970–2286 range).
- 13 digits ~ milliseconds.
- 16 digits ~ microseconds.
Always confirm with source docs. If unsure, convert and sanity‑check the result.
Step 2: Convert in Popular Languages
JavaScript / TypeScript
// Seconds → Date (UTC output)
const sec = 1697040000;
console.log(new Date(sec * 1000).toISOString()); // 2023-10-11T00:00:00.000Z
// Milliseconds → Date
const ms = 1697040000000;
console.log(new Date(ms).toISOString());
// Date → Seconds
const d = new Date('2023-10-11T00:00:00Z');
const epochSeconds = Math.floor(d.getTime() / 1000);
Python (3.x)
from datetime import datetime, timezone
# Seconds → ISO 8601 (UTC)
sec = 1697040000
dt = datetime.fromtimestamp(sec, tz=timezone.utc)
print(dt.isoformat().replace('+00:00', 'Z'))
# Milliseconds → ISO 8601 (UTC)
ms = 1697040000000
dt = datetime.fromtimestamp(ms / 1000, tz=timezone.utc)
print(dt.isoformat().replace('+00:00', 'Z'))
# Date → Epoch seconds (UTC)
d = datetime(2023, 10, 11, 0, 0, 0, tzinfo=timezone.utc)
print(int(d.timestamp()))
Bash / Shell (GNU date)
# Seconds → Local time
TS=1697040000; date -d @"$TS"
# Seconds → UTC ISO 8601
date -u -d @"$TS" +"%Y-%m-%dT%H:%M:%SZ"
# Milliseconds → convert
MS=1697040000000; date -u -d @"$((MS/1000))" +"%Y-%m-%dT%H:%M:%SZ"
# Date → Epoch seconds
date -u -d "2023-10-11T00:00:00Z" +%s
PHP
// Seconds → ISO 8601 (UTC)
$sec = 1697040000;
echo gmdate('c', $sec); // 2023-10-11T00:00:00+00:00
// Milliseconds → ISO 8601 (UTC)
$ms = 1697040000000;
echo gmdate('c', intdiv($ms, 1000));
// Date → Epoch seconds (UTC)
echo (new DateTime('2023-10-11T00:00:00Z'))->getTimestamp();
Java
import java.time.*;
long sec = 1697040000L;
Instant instant = Instant.ofEpochSecond(sec);
System.out.println(instant.toString()); // UTC ISO 8601
long ms = 1697040000000L;
Instant instantMs = Instant.ofEpochMilli(ms);
// Date → Epoch seconds
ZonedDateTime zdt = ZonedDateTime.parse("2023-10-11T00:00:00Z");
long epochSeconds = zdt.toEpochSecond();
C# (.NET)
using System;
long sec = 1697040000;
var dtUtc = DateTimeOffset.FromUnixTimeSeconds(sec).UtcDateTime;
Console.WriteLine(dtUtc.ToString("o")); // ISO 8601
long ms = 1697040000000;
var dtMs = DateTimeOffset.FromUnixTimeMilliseconds(ms).UtcDateTime;
// Date → Epoch seconds
var when = DateTimeOffset.Parse("2023-10-11T00:00:00Z");
Console.WriteLine(when.ToUnixTimeSeconds());
SQL
-- Seconds → timestamp with time zone (UTC display)
SELECT to_timestamp(1697040000) AT TIME ZONE 'UTC';
-- Milliseconds → divide first
SELECT to_timestamp(1697040000000 / 1000.0) AT TIME ZONE 'UTC';
-- Date → epoch seconds
SELECT EXTRACT(EPOCH FROM TIMESTAMPTZ '2023-10-11T00:00:00Z');
-- Seconds → datetime (assumes UTC if using FROM_UNIXTIME)
SELECT FROM_UNIXTIME(1697040000);
-- Milliseconds → divide
SELECT FROM_UNIXTIME(1697040000000 / 1000);
-- Date → epoch seconds
SELECT UNIX_TIMESTAMP('2023-10-11 00:00:00'); -- server time_zone sensitive
-- Seconds → UTC
SELECT datetime(1697040000, 'unixepoch');
-- Milliseconds → divide
SELECT datetime(1697040000000 / 1000, 'unixepoch');
-- Date → epoch seconds
SELECT strftime('%s', '2023-10-11T00:00:00Z');
Step 3: Handle Time Zones
- Convert to UTC first for accuracy.
- Only then apply a display zone:
- JavaScript (Intl):
const dt = new Date(1697040000 * 1000);
console.log(dt.toLocaleString('en-US', { timeZone: 'America/New_York' }));
- Python (zoneinfo):
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
dt = datetime.fromtimestamp(1697040000, tz=timezone.utc)
print(dt.astimezone(ZoneInfo('America/New_York'))) # DST-aware
- Avoid hardcoding offsets like -0500. Use IANA names (e.g., America/New_York).
Step 4: Format Output (ISO 8601)
Use ISO 8601 strings for APIs and logs:
- UTC: 2023-10-11T00:00:00Z
- With offset: 2023-10-11T02:00:00+02:00
Tips:
- In JavaScript, prefer toISOString() for UTC.
- In Python, use .isoformat() and append ‘Z’ for UTC.
- Be consistent across services.
Step 5: Convert Dates Back to Epoch
Examples:
- JS:
Math.floor(new Date('2023-10-11T00:00:00Z').getTime()/1000)
- Python:
int(datetime(2023,10,11,tzinfo=timezone.utc).timestamp())
- Bash:
date -u -d '2023-10-11T00:00:00Z' +%s
- PostgreSQL:
EXTRACT(EPOCH FROM TIMESTAMPTZ '2023-10-11T00:00:00Z')
Step 6: Validate and Test
- Cross-check with two tools or languages.
- Verify around DST transitions.
- Keep known “golden” samples in tests.
- Document the unit (seconds vs. milliseconds) in your schema.
Real World Examples
1) Log Correlation Across Services
- Problem: Logs in different time zones and formats.
- Fix: Convert Unix epoch to UTC ISO 8601 everywhere; use IDs to correlate. Example: 1697040000 → 2023‑10‑11T00:00:00Z.
2) Analytics Dashboards
- Web events often use milliseconds. If your BI tool expects seconds, divide by 1000 before conversion to avoid 1970 dates.
3) APIs and Webhooks
- Many APIs return seconds (Stripe) or milliseconds (Firebase). Normalize to UTC, store as integer seconds, and format to ISO only at output.
4) Databases and Time Zones
- PostgreSQL’s TIMESTAMPTZ stores a moment in time, displayed per time zone. TIMESTAMP (without TZ) can cause ambiguous values around DST.
5) IoT and Edge Devices
- Devices send epoch when offline. On ingestion, convert to UTC immediately and tag device’s intended zone for later display.
6) Security and Audit Trails
- Write ISO 8601 with ‘Z’ for UTC in append‑only logs. Auditors expect clear, unambiguous times.
Common Mistakes
- Mixing seconds and milliseconds.
- Assuming local time instead of UTC.
- Hardcoding offsets instead of using IANA time zones.
- Ignoring DST and getting one-hour shifts.
- Using 32‑bit ints for future dates (overflow risks in 2038 on legacy systems).
- Formatting without zero padding or time zone info.
- Parsing locale-dependent strings (e.g., “03/04/2024”) instead of ISO.
Best Practices
- Store epoch in integers; document the unit.
- Normalize to UTC at ingestion; convert for display only.
- Use ISO 8601 in APIs and logs.
- Prefer IANA time zones (America/Los_Angeles) over fixed offsets.
- Add tests near DST changes and leap-year dates.
- For databases, use TIMESTAMPTZ (or equivalent) for moments in time.
- Version your time-handling code and keep a reference sheet of scary timestamps.
Expert Tips
- For performance, avoid repeated time zone conversions in tight loops; cache formatters.
- If you need subsecond precision, store milliseconds or microseconds as integers plus a documented scale.
- In Java, java.time (Instant/ZonedDateTime) beats legacy Date/Calendar.
- In Python, use timezone-aware datetimes (tzinfo not None). zoneinfo is in the stdlib (3.9+).
- Keep servers NTP‑synced; bad clocks cause bad data.
- When indexing by time, store epoch seconds in a separate column for faster range scans.
Comparison Table
| Scenario | Input Unit | Example Input | Safe Conversion (UTC) | Typical Output |
|---|
| JS seconds to date | seconds | 1697040000 | new Date(sec * 1000).toISOString() | 2023-10-11T00:00:00.000Z |
| JS ms to date | milliseconds | 1697040000000 | new Date(ms).toISOString() | 2023-10-11T00:00:00.000Z |
| Python seconds | seconds | 1697040000 | datetime.fromtimestamp(sec, tz=UTC) | 2023-10-11T00:00:00+00:00 |
| Python ms | milliseconds | 1697040000000 | datetime.fromtimestamp(ms/1000, tz=UTC) | 2023-10-11T00:00:00+00:00 |
| PostgreSQL seconds | seconds | 1697040000 | to_timestamp(sec) AT TIME ZONE 'UTC' | 2023-10-11 00:00:00 |
| MySQL seconds | seconds | 1697040000 | FROM_UNIXTIME(sec) | 2023-10-11 00:00:00 |
Notes:
- Replace UTC with your display zone as needed.
- Always check whether units are seconds or milliseconds.
Frequently Asked Questions
- What is Unix epoch?
- The Unix epoch is the starting point for Unix time: 1970‑01‑01T00:00:00Z. Timestamps count seconds (or milliseconds) since then.
- How do I detect seconds vs. milliseconds?
- Check length and magnitude: 10 digits ≈ seconds, 13 ≈ milliseconds. Validate by converting and seeing if the date is plausible.
- Why do my dates show 1970?
- You likely treated milliseconds as seconds. Divide by 1000 or use an API that accepts milliseconds.
- How do I convert Unix epoch in JavaScript?
- Use new Date(seconds * 1000) or new Date(milliseconds), then toISOString() for UTC output.
- How do I convert in Python?
- Use datetime.fromtimestamp(sec, tz=timezone.utc), or divide milliseconds by 1000 first.
- What’s the difference between UTC and GMT?
- For most programming uses, treat them the same. UTC is the standard; use ‘Z’ in ISO strings for UTC.
- Does DST affect Unix epoch?
- The epoch itself is zone‑neutral. DST matters only when you display or parse in a local time zone.
- Are leap seconds included?
- POSIX time ignores leap seconds. Most libraries smooth them out; treat Unix time as continuous seconds.
- What about negative timestamps (before 1970)?
- Many systems handle them, but not all. Test if you need historical dates.
- Should I store epoch as an integer or string?
- Prefer integer for speed, space, and easy math. Document the unit.
- How do I format with time zone offsets?
- Use ISO 8601 with an offset, e.g., 2023‑10‑11T02:00:00+02:00. Convert from UTC with an IANA time zone first.
- Is TIMESTAMP WITH TIME ZONE the same as storing UTC?
- In PostgreSQL, TIMESTAMPTZ stores an absolute moment and displays in the current time zone by default. It’s safe for moments in time.
- How can I convert in SQL Server?
- Use DATEADD and DATEDIFF with '19700101', or AT TIME ZONE for zone handling. Example: DATEADD(SECOND, @sec, '19700101') AT TIME ZONE 'UTC'.
- How do I handle microseconds?
- Store as a 64‑bit integer. When converting, divide by 1,000,000 (or use microsecond‑aware APIs) and preserve precision.
- What’s the safest display format?
- ISO 8601 in UTC (with ‘Z’). It’s unambiguous, sortable, and widely supported.
External References
- Unix Timestamp Converter (seconds ↔ milliseconds ↔ ISO 8601)
- Time Zone Converter (UTC ↔ local, IANA zones)
- Date Difference Calculator (durations, SLAs)
- Log Formatter & Correlator (parse timestamps, standardize)
- JSON Formatter & Validator (for API payloads with dates)
Conclusion
To convert Unix epoch reliably, identify the unit first, convert in UTC, then format using ISO 8601. Use IANA time zones for display and test around DST. With the steps and code above, you can convert Unix epoch across stacks without surprises—and keep your data, logs, and reports consistent.
Call To Action
Convert Unix epoch in seconds or milliseconds instantly with ZenixTools. Try the Unix Timestamp Converter, validate your time zones, and export clean ISO 8601 strings for your apps, dashboards, and audits.