Guides
Invalid Timestamp: Quick Diagnostics and Fixes
The quick diagnostic checklist
- Check length: 10=seconds, 13=ms, 16=µs, 19=ns.
- Check digits: numbers only; remove spaces/letters.
- Check range: is the resulting date plausible and 64-bit safe?
- Check timezone: convert in UTC first, then apply target offset.
- Check DST edge: if localizing, use an IANA zone (
America/New_York).
Need to verify right now? Jump to Unix Timestamp Converter or Batch Converter.
Common error types
- Length mismatch: 13-digit treated as seconds → far future date.
- Non-digit characters: hidden spaces, commas, or letters.
- Out-of-range: 32-bit seconds overflow beyond 2038; negatives unsupported in some systems.
- Timezone ambiguity: server local time vs. expected UTC.
- DST shifts: parsing into local time during the missing hour causes failure.
Validation steps (copy-paste)
// JavaScript: validate & normalize to milliseconds
export function normalizeEpoch(raw) {
const trimmed = raw.trim();
if (!/^[0-9]+$/.test(trimmed)) throw new Error("Digits only");
const len = trimmed.length;
if (len === 10) return Number(trimmed) * 1000;
if (len === 13) return Number(trimmed);
if (len === 16) return Number(trimmed) / 1000;
if (len === 19) return Number(trimmed) / 1_000_000;
throw new Error("Invalid length");
}
# Python: validate & to datetime (UTC)
from datetime import datetime, timezone
def parse_epoch(raw: str) -> datetime:
if not raw.isdigit():
raise ValueError("Digits only")
n = len(raw)
if n == 10:
ts = int(raw)
elif n == 13:
ts = int(raw) / 1000
elif n == 16:
ts = int(raw) / 1_000_000
elif n == 19:
ts = int(raw) / 1_000_000_000
else:
raise ValueError("Invalid length")
return datetime.fromtimestamp(ts, tz=timezone.utc)
-- SQL (PostgreSQL): validate timestamp length in a table
SELECT id, ts_raw,
CASE
WHEN ts_raw ~ '^[0-9]{10}$' THEN 'seconds'
WHEN ts_raw ~ '^[0-9]{13}$' THEN 'milliseconds'
WHEN ts_raw ~ '^[0-9]{16}$' THEN 'microseconds'
WHEN ts_raw ~ '^[0-9]{19}$' THEN 'nanoseconds'
ELSE 'invalid'
END AS ts_precision
FROM events
WHERE ts_raw !~ '^[0-9]{10}$'
OR ts_raw::numeric > 32503680000; -- > 3000-01-01 as a sanity bound
Fix templates
- Precision fix: detect length → scale to milliseconds → re-run parsing.
- Trim / sanitize: strip whitespace and commas before regex validation.
- Range guard: cap or discard values outside plausible window (e.g., year
< 2000or> 2100). - Timezone fix: parse as UTC, then format to user’s target offset/zone.
- DST-safe parsing: prefer UTC; if local is required, use IANA zone libraries.
FAQ
- What’s the safest default? Parse as UTC, then format to the requested timezone.
- How do I prevent 2038 issues? Store as 64-bit integers; avoid 32-bit second-based storage.
- How to batch clean data? Use a regex pre-filter + length-based scaling, then pipe into a converter; try Batch Timestamp Converter.