Guides
Timestamp to ISO 8601 Converter (Seconds, Millis, Nanos)
Why this page
You often get timestamps in seconds (10 digits), milliseconds (13), microseconds (16), or nanoseconds (19). This page gives you one-stop rules, ready-to-ship snippets, and CTAs to the full converter so you can turn any epoch into ISO 8601 / RFC 3339 without guessing the precision.
Quick start (MVP flow)
- Paste the timestamp (we auto-detect length and precision).
- Choose timezone:
UTCor custom offset (e.g.,UTC+08:00). - Get ISO 8601 / RFC 3339 output, then one-click copy.
- Need to embed? Copy a language snippet below.
Try the interactive tool: Timestamp → ISO Converter and Format Builder.
Input rules and validation
- Length detection: 10=seconds, 13=ms, 16=µs, 19=ns.
- Allowed chars: digits only; reject whitespace and letters.
- Range: must be within platform-safe bounds (check 32-bit vs 64-bit; see FAQ).
- Timezone: default UTC; custom offsets like
+08:00,-05:30. - DST: the output uses offset-aware ISO 8601; UTC avoids DST surprises.
Code snippets
JavaScript / Node.js
const detectPrecision = (raw) => {
const len = raw.length;
if (len === 10) return { value: Number(raw) * 1000, unit: "ms" };
if (len === 13) return { value: Number(raw), unit: "ms" };
if (len === 16) return { value: Number(raw) / 1000, unit: "ms" }; // µs → ms
if (len === 19) return { value: Number(raw) / 1_000_000, unit: "ms" }; // ns → ms
throw new Error("Invalid length");
};
const toIso = (raw, tz = "UTC") => {
const { value } = detectPrecision(raw);
// If you need a fixed offset, use luxon or temporal; here we show UTC
return new Date(value).toISOString(); // RFC 3339 compliant
};
console.log(toIso("1704067200")); // 10 digits -> seconds
console.log(toIso("1704067200000")); // 13 digits -> milliseconds
Python
from datetime import datetime, timezone, timedelta
def to_iso(raw: str, offset_minutes: int = 0) -> str:
length = len(raw)
if length == 10:
ts = int(raw)
elif length == 13:
ts = int(raw) / 1000
elif length == 16:
ts = int(raw) / 1_000_000
elif length == 19:
ts = int(raw) / 1_000_000_000
else:
raise ValueError("Invalid length")
tz = timezone(timedelta(minutes=offset_minutes))
return datetime.fromtimestamp(ts, tz=tz).isoformat()
print(to_iso("1704067200", 0)) # UTC
print(to_iso("1704067200000", 480)) # UTC+08:00
Go
package main
import (
"fmt"
"time"
)
func parseEpoch(raw string) (time.Time, error) {
switch len(raw) {
case 10:
sec, _ := time.ParseInt(raw, 10, 64)
return time.Unix(sec, 0).UTC(), nil
case 13:
ms, _ := time.ParseInt(raw, 10, 64)
return time.Unix(0, ms*int64(time.Millisecond)).UTC(), nil
case 16:
us, _ := time.ParseInt(raw, 10, 64)
return time.Unix(0, us*int64(time.Microsecond)).UTC(), nil
case 19:
ns, _ := time.ParseInt(raw, 10, 64)
return time.Unix(0, ns).UTC(), nil
default:
return time.Time{}, fmt.Errorf("invalid length")
}
}
func main() {
t, err := parseEpoch("1704067200000")
if err != nil {
panic(err)
}
fmt.Println(t.Format(time.RFC3339))
}
Common pitfalls
- Wrong precision: 13-digit JS timestamps treated as seconds = huge future date.
- Missing offset: local parsing without specifying timezone yields machine-local time.
- DST edges: if you must show local time, pick a real IANA zone (e.g.,
America/New_York) rather than a fixed offset. - Overflow: 32-bit systems will break after 2038 for second-level timestamps; prefer 64-bit.
FAQ
- Q: Seconds vs milliseconds—how do I tell?
A: Check digit length; if uncertain, run both and see which is in a plausible date window. - Q: Does ISO 8601 require
Z?
A:Zmeans UTC. Any offset like+08:00is also valid ISO 8601 / RFC 3339. - Q: Can I batch convert?
A: Use Batch Timestamp Converter.