2001 wasn’t random
Apple picked 2001-01-01—the launch year of Mac OS X—so the reference date sits in the modern era and starts on a Monday.
If you exported an iOS or macOS SQLite database such as Safari History.db, iMessage chat.db, or app Core Data tables, those strange Apple reference-date values usually use this exact 2001 epoch.
Looking for timestamps based on Apple’s older 1904 epoch instead? Try the Mac HFS+ (1904 epoch) converter.
978307200 seconds (to/from 1970-01-01 UTC)NSDate.timeIntervalSinceReferenceDate returns. If you paste an 18-digit Apple timestamp, the converter treats it as nanoseconds automatically.
If you work with Apple platforms, you will eventually meet CFAbsoluteTime. It is the time value used by Core Foundation and Cocoa, and it can look unfamiliar at first. This converter helps you translate CFAbsoluteTime into a normal date and time, and it lets you convert a human-readable date back into Apple’s reference time. Whether you are debugging an iOS log, checking an NSDate value, or migrating data between systems, this tool makes the conversion simple and accurate.
The same epoch also appears in many real-world exports under different names: Core Data timestamp, Mac absolute time, NSDate reference date, or just a mysterious integer from an Apple SQLite database. If you pulled rows from Safari history, iMessage, Notes, or another iOS/macOS app and saw a value that does not look like Unix time, it is often this 2001-based timestamp.
CFAbsoluteTime (often surfaced by NSDate reference-date APIs as an NSTimeInterval) counts the number of seconds,
including fractions, since Apple’s reference date of 2001-01-01 00:00:00 UTC. Unix time uses a different
reference point: 1970-01-01 00:00:00 UTC. That means Apple time is offset from Unix time by a fixed number of
seconds. This calculator applies that offset for you so you do not have to do the math manually.
The key conversion is straightforward: the Apple reference date occurs exactly 978,307,200 seconds after the
Unix epoch. If you need the formulas, they are:
CF → UNIX seconds is unix = cf + 978307200, and
UNIX seconds → CF is cf = unix - 978307200. The tool keeps millisecond precision so
you can compare values accurately across systems.
Real-world uses include interpreting timestamps in crash logs, converting dates stored in Core Data, comparing API responses that use Unix timestamps, or synchronizing event times between iOS apps and backend services. If you have a log entry showing an NSTimeInterval and you want to know the actual date, this tool shows it in a readable format right away.
Some Apple frameworks and exports store the same value in nanoseconds instead of seconds. That is
why values such as 590517794000000000 look absurdly large. This tool auto-detects those oversized
inputs and divides by 1,000,000,000 before conversion so you do not land in a wildly incorrect year.
Time zones matter only when you display the result. The underlying CFAbsoluteTime value is UTC-based, so the stored number does not change across regions. If you provide a date with a specific time zone or offset, the converter respects it and calculates the correct absolute time.
Quick, copyable examples for converting between CFAbsoluteTime (seconds since 2001-01-01T00:00:00Z) and human time.
// CFAbsoluteTime ("since 2001") ↔ UNIX seconds ("since 1970")
let offset: TimeInterval = 978_307_200
func cfToUnix(_ cf: TimeInterval) -> TimeInterval { cf + offset }
func unixToCf(_ unix: TimeInterval) -> TimeInterval { unix - offset }
// CFAbsoluteTime ↔ Date
func cfToDate(_ cf: TimeInterval) -> Date {
Date(timeIntervalSince1970: cf + offset)
}
func dateToCf(_ date: Date) -> TimeInterval {
date.timeIntervalSince1970 - offset
}
static const NSTimeInterval kOffset = 978307200.0;
NSTimeInterval CFToUnix(NSTimeInterval cf) { return cf + kOffset; }
NSTimeInterval UnixToCF(NSTimeInterval unix) { return unix - kOffset; }
NSDate * CFToDate(NSTimeInterval cf) { return [NSDate dateWithTimeIntervalSince1970:(cf + kOffset)]; }
NSTimeInterval DateToCF(NSDate *date) { return [date timeIntervalSince1970] - kOffset; }
const OFFSET = 978307200;
function cfToDate(cf) { return new Date((cf + OFFSET) * 1000); }
function dateToCf(d) { return d.getTime() / 1000 - OFFSET; }
=(A1 / 86400) + DATE(2001,1,1)
SELECT datetime(ZDATE + 978307200, 'unixepoch')
FROM ZTABLE;
OFFSET = 978_307_200
def cf_to_datetime(cf):
import datetime
return datetime.datetime.fromtimestamp(cf + OFFSET, tz=datetime.timezone.utc)
def datetime_to_cf(dt):
if dt.tzinfo is None: dt = dt.astimezone()
return dt.timestamp() - OFFSET
OFFSET = 978_307_200.0
def cf_to_time(cf) Time.at(cf + OFFSET).utc end
def time_to_cf(t) t.to_f - OFFSET end
[NSDate timeIntervalSinceReferenceDate] returns CFAbsoluteTime.Apple picked 2001-01-01—the launch year of Mac OS X—so the reference date sits in the modern era and starts on a Monday.
Add 978307200 seconds to hop between CFAbsoluteTime and UNIX time. That’s exactly 31 years plus 8 leap days.
Dates before 2001 show up as negatives—1999-12-31 is -31708800 seconds. Handy when parsing old logs.
NSDate and CFDate are toll-free bridged; both wrap the same underlying double seconds since 2001 in memory.
A 64-bit double keeps roughly 0.2 μs resolution around today’s timestamps—plenty of headroom before precision drifts.