1960 was chosen on purpose
The SAS epoch 1960-01-01 is the first leap year of that decade and sits between COBOL’s 1960 defaults and IBM mainframe calendars—handy for 60s-era data.
Run a conversion below to see detailed outputs here.
SAS datetime counts seconds (fractional allowed) since 1960-01-01T00:00:00Z. SAS date counts whole days since 1960-01-01.
unix = sasSec − 315,619,200; sasSec = unix + 315,619,200sasDays = floor(unix / 86,400) + 3,653; unix ≈ (sasDays − 3,653) × 86,400Convert between SAS datetime seconds / date days and ISO-8601 dates.
const SAS_UNIX_OFFSET_SEC = 315_619_200; // 1960→1970
function unixToSasSeconds(unixSec){ return unixSec + SAS_UNIX_OFFSET_SEC; }
function sasSecondsToUnix(sasSec){ return sasSec - SAS_UNIX_OFFSET_SEC; }
function sasSecondsToDate(sasSec){ return new Date((sasSec - SAS_UNIX_OFFSET_SEC) * 1000); }
function dateToSasSeconds(d){ return d.getTime()/1000 + SAS_UNIX_OFFSET_SEC; }
function unixToSasDays(unixSec){ return Math.floor(unixSec/86400) + 3653; }
function sasDaysToUnix(sasDays){ return (sasDays - 3653) * 86400; }
import datetime
SAS_UNIX_OFFSET_SEC = 315_619_200
def sas_seconds_to_datetime(s): return datetime.datetime.fromtimestamp(s - SAS_UNIX_OFFSET_SEC, tz=datetime.timezone.utc)
def datetime_to_sas_seconds(dt):
if dt.tzinfo is None: dt = dt.astimezone()
return dt.timestamp() + SAS_UNIX_OFFSET_SEC
def sas_days_to_date(d): # returns date at 00:00 UTC
sec = (d - 3653) * 86400
return datetime.datetime.fromtimestamp(sec, tz=datetime.timezone.utc)
The SAS epoch 1960-01-01 is the first leap year of that decade and sits between COBOL’s 1960 defaults and IBM mainframe calendars—handy for 60s-era data.
The Unix ↔ SAS seconds gap is 315,619,200 seconds, a tidy 0x12D53D80. Add or subtract it to hop epochs instantly.
SAS date day 3,653 equals 1970-01-01. Negative days walk backward: -3,653 is 1949-12-31.
SAS datetime values can include decimals. The converter keeps sub-second precision intact when jumping between SAS seconds and ISO strings.
Excel’s default epoch is 1899; SAS is 1960. Converting between them requires two offsets: Excel ↔ Unix, then Unix ↔ SAS—so two hops, not one.