SAS Date & Datetime Functions
Quick reference for date and datetime handling in SAS Base. Understanding SAS's numeric date representation is essential for working with dates correctly.
How SAS Stores Dates
SAS dates are numbers. A SAS date is an integer counting days since 1 January 1960 (= 0). Dates before 1960 are negative. A SAS datetime is seconds since midnight 1 January 1960. A SAS time is seconds since midnight of the current day.
| Type | Unit | Epoch | Example value |
|---|---|---|---|
| Date | Days (integer) | 1 Jan 1960 = 0 | 1 Jan 2024 = 23376 |
| Datetime | Seconds (can be fractional) | 1 Jan 1960 00:00:00 = 0 | 1 Jan 2024 12:00 = 2,019,686,400 |
| Time | Seconds since midnight | 00:00:00 = 0 | 14:30:00 = 52200 |
Always apply a format (e.g. DATE9., DATETIME20.) to display dates as human-readable values. Without a format, SAS displays the raw number.
Date Literals
| Literal | Type | Example |
|---|---|---|
'ddMONyyyy'D | Date | '15MAR2024'D |
'ddMONyyyy:hh:mm:ss'DT | Datetime | '15MAR2024:14:30:00'DT |
'hh:mm:ss'T | Time | '14:30:00'T |
Current Date & Time
| Function | Returns | Type |
|---|---|---|
TODAY() | Today's date | SAS date |
DATE() | Today's date (synonym) | SAS date |
DATETIME() | Current datetime | SAS datetime |
TIME() | Current time of day | SAS time |
Extracting Date Parts
| Function | Description | Example | Result |
|---|---|---|---|
YEAR(date) | 4-digit year | YEAR('15MAR2024'D) | 2024 |
MONTH(date) | Month (1–12) | MONTH('15MAR2024'D) | 3 |
DAY(date) | Day of month (1–31) | DAY('15MAR2024'D) | 15 |
WEEKDAY(date) | Day of week (1=Sunday) | WEEKDAY('15MAR2024'D) | 6 (Friday) |
QTR(date) | Quarter (1–4) | QTR('15MAR2024'D) | 1 |
HOUR(time_or_dt) | Hour (0–23) | HOUR('14:30:00'T) | 14 |
MINUTE(time_or_dt) | Minute (0–59) | MINUTE('14:30:00'T) | 30 |
SECOND(time_or_dt) | Second (0–59) | SECOND('14:30:45'T) | 45 |
WEEK(date, opt) | Week of year (opt controls start day) | WEEK('15MAR2024'D, 'V') | ISO week number |
Date Arithmetic
Because SAS dates are integers, arithmetic is often direct:
days_between = end_date - start_date; /* exact day difference */ tomorrow = today() + 1; last_week = today() - 7;
| Function | Description | Example | Result |
|---|---|---|---|
INTNX(interval, date, n) | Advance by n intervals (returns start of interval) | INTNX('month', '15MAR2024'D, 1) | 01APR2024 |
INTNX('month', date, 0, 'E') | End of current month ('B'=begin, 'M'=middle, 'E'=end, 'S'=same) | INTNX('month','15MAR2024'D, 0,'E') | 31MAR2024 |
INTNX('year', date, 0, 'B') | Start of current year | INTNX('year', today(), 0, 'B') | 1 Jan of current year |
INTCK(interval, start, end) | Count intervals between dates | INTCK('month','01JAN2024'D,'15MAR2024'D) | 2 |
INTCK('month', start, end, 'C') | Continuous count (fractional crossing) | may differ from default |
INTNX vs direct arithmetic: Use
INTNX when you want to stay aligned to interval boundaries (e.g. start/end of month). Use direct arithmetic for exact day counts.Converting Between Date Types
| Function | Description | Example |
|---|---|---|
DATEPART(datetime) | Extract date from datetime | DATEPART('15MAR2024:14:30:00'DT) → SAS date |
TIMEPART(datetime) | Extract time from datetime | TIMEPART('15MAR2024:14:30:00'DT) → SAS time |
DHMS(date, h, m, s) | Build datetime from date + time parts | DHMS('15MAR2024'D, 14, 30, 0) → SAS datetime |
HMS(h, m, s) | Build time from parts | HMS(14, 30, 0) → 52200 |
MDY(m, d, y) | Build date from month/day/year | MDY(3, 15, 2024) → SAS date |
YYQ(y, q) | First day of quarter | YYQ(2024, 1) → 1 Jan 2024 |
Parsing Strings to Dates
| Approach | Description | Example |
|---|---|---|
INPUT(str, informat) | Parse character string with date informat | INPUT('2024-03-15', YYMMDD10.) |
INPUT(str, DATE9.) | Parse ddMONyyyy format | INPUT('15MAR2024', DATE9.) |
INPUT(str, DDMMYY10.) | Parse dd/mm/yyyy format | INPUT('15/03/2024', DDMMYY10.) |
INPUT(str, ANYDTDTE.) | Flexible informat — tries many formats automatically | INPUT('March 15 2024', ANYDTDTE.) |
INPUT(str, DATETIME.) | Parse datetime string | INPUT('15MAR2024:14:30:00', DATETIME.) |
Always assign the correct format after parsing: FORMAT date_var DATE9.;. Without this the variable displays as a number.
Formatting Dates as Strings
| Format | Example output | Example input |
|---|---|---|
DATE9. | 15MAR2024 | SAS date |
DATE7. | 15MAR24 | SAS date |
DDMMYY10. | 15/03/2024 | SAS date |
MMDDYY10. | 03/15/2024 | SAS date |
YYMMDD10. | 2024-03-15 | SAS date |
WORDDATE. | March 15, 2024 | SAS date |
MONYY7. | MAR2024 | SAS date |
DATETIME20. | 15MAR2024:14:30:00 | SAS datetime |
DATETIME21.2 | 15MAR2024:14:30:00.00 | SAS datetime |
TIME8. | 14:30:00 | SAS time |
/* Apply format in DATA step */ FORMAT date_var YYMMDD10.; /* Convert to character string using PUT */ date_str = PUT(date_var, YYMMDD10.); /* '2024-03-15' */
Common Patterns
/* First day of current month */
first_of_month = intnx('month', today(), 0, 'B');
format first_of_month date9.;
/* Last day of current month */
end_of_month = intnx('month', today(), 0, 'E');
/* First day of current year */
first_of_year = intnx('year', today(), 0, 'B');
/* Age in years */
age = intck('year', birthdate, today());
/* Adjust if birthday hasn't occurred this year yet */
if month(birthdate) > month(today()) or
(month(birthdate) = month(today()) and day(birthdate) > day(today()))
then age = age - 1;
/* Quarter start date */
qtr_start = intnx('qtr', today(), 0, 'B');
/* Parse ISO date string from source data */
date_var = input(date_str, yymmdd10.);
format date_var date9.;
/* Check if date falls on a weekend */
if weekday(date_var) in (1, 7) then is_weekend = 1;
/* 1=Sunday, 7=Saturday */
/* Datetime to date */
date_only = datepart(dt_var);
format date_only date9.