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.
978307200 seconds (to/from 1970-01-01 UTC)NSDate.timeIntervalSinceReferenceDate returns.
CFAbsoluteTime (also known as NSTimeInterval when used by NSDate) counts seconds—
possibly fractional—since the Apple reference date 2001-01-01T00:00:00Z. This converter translates
between that value and human-readable dates, preserving millisecond precision in outputs.
Compared to the UNIX epoch (1970-01-01T00:00:00Z), the Apple reference date occurs exactly
978,307,200 seconds later. Conversions are therefore:
unix = cf + 978307200cf = unix - 978307200Quick, 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; }
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 about -31622400 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.