5.3 Working with SAS Dates, Times, & Intervals

Key Takeaways

  • A SAS date value is stored as an integer representing the exact number of days elapsed since January 1, 1960.
  • SAS time values represent seconds past midnight (0 to 86,400), while datetime values represent seconds elapsed since January 1, 1960 midnight.
  • MDY(month, day, year) constructs a SAS date value from three numeric arguments, while YEAR, QTR, MONTH, and DAY extract those calendar components back out of an existing SAS date value.
  • INTCK counts the number of interval boundaries crossed between two dates, not the exact duration of elapsed time.
  • INTNX advances a starting date by a specified number of intervals and aligns the resulting date to the beginning, middle, end, or same relative position of the interval.
Last updated: August 2026

5.3 Working with SAS Dates, Times, & Intervals

Handling calendar dates, clock times, and time-series intervals is a cornerstone of business analytics. SAS handles date and time values using a unique internal numeric representation. Understanding how SAS stores date values, how formats display them, and how date functions calculate intervals is vital for writing bug-free programs and passing the SAS Base exam.


1. Internal Storage of SAS Dates, Times, & Datetimes

Rather than storing dates as text strings (such as "2026-01-01"), SAS stores all date and time values as internal numeric values relative to specific baseline epochs:

  • SAS Date Value: An integer representing the number of days between January 1, 1960 and the specified date.
    • January 1, 1960 = 0
    • January 2, 1960 = 1
    • December 31, 1959 = -1
    • January 1, 2026 = 24107
  • SAS Time Value: A numeric value representing the number of seconds past midnight (ranges from 0 to 86400).
  • SAS Datetime Value: A numeric value representing the number of seconds between midnight on January 1, 1960 and the specified date/time.

Date, Time, and Datetime Literals

To write literal date, time, or datetime constants directly in SAS code, enclose the string in single or double quotes followed immediately by d, t, or dt:

data work.literals;
    d_val  = '01JAN2026'd;     /* SAS date value: 24107 */
    t_val  = '14:30:00't;      /* SAS time value: 52200 seconds */
    dt_val = '01JAN2026:14:30:00'dt; /* SAS datetime value */
run;

2. Date Creation & Extraction Functions

SAS provides built-in functions to build date values from individual components and to extract components from existing SAS date values.

Building Dates: MDY and DATEJUL

  • MDY(month, day, year): Creates a SAS date value from month (1–12), day (1–31), and year values.
  • DATEJUL(julian_date): Converts a 5-digit or 7-digit Julian date (YYDDD or YYYYDDD) into a SAS date value.
  • TODAY() or DATE(): Returns the current date as a SAS date value based on the system clock. The two are aliases and return an identical value.
  • TIME(): Returns the current clock time as a SAS time value — seconds past midnight, not a date. Apply a TIME8. format to display it as hh:mm:ss.

TODAY(), DATE(), and TIME() take no arguments, but the empty parentheses are still required: writing current = today; creates an uninitialized variable named today rather than calling the function, which is a classic exam distractor.

data work.build_dates;
    m = 7; d = 4; y = 2026;
    july4th = mdy(m, d, y);            /* Returns SAS date for July 4, 2026 */
    current = today();                 /* Current system date */
    clock   = time();                  /* Current time, seconds past midnight */
    format july4th current date9. clock time8.;
run;

Extracting Date Components

Given a valid SAS date integer, you can extract specific calendar components. The exam names four extraction functions explicitly — YEAR, QTR, MONTH, and DAY:

FunctionReturns'15AUG2026'd yields
YEAR(date)4-digit calendar year2026
QTR(date)Quarter of the year, 143
MONTH(date)Month number, 1128
DAY(date)Day of the month, 13115
WEEKDAY(date)Day of the week, 1=Sunday7
data work.extract_dates;
    sample_date = '15AUG2026'd;
    
    day_num   = day(sample_date);     /* Returns 15 */
    month_num = month(sample_date);   /* Returns 8  */
    qtr_num   = qtr(sample_date);     /* Returns 3 (August sits in Quarter 3) */
    year_num  = year(sample_date);    /* Returns 2026 */
    wday_num  = weekday(sample_date); /* Returns 7 (1=Sunday, 7=Saturday) */
run;

[!WARNING] Do not confuse the QTR() function with the 'QTR' interval string. qtr(d) takes a date argument and returns the quarter number 1–4. intck('QTR', d1, d2) and intnx('QTR', d, 1) pass 'QTR' as a quoted interval name to a different function entirely. The same trap applies to YEAR, MONTH, and DAY, which are all both extraction functions and interval names.


3. Interval Counting with INTCK

The INTCK function counts the number of interval boundaries crossed between two SAS date, time, or datetime values.

Syntax: INTCK(interval,start-date,end-date,<method>)\text{Syntax: } \text{INTCK}('\textit{interval}', \textit{start-date}, \textit{end-date}, <'\textit{method}'>)

Supported intervals include 'DAY', 'WEEK', 'MONTH', 'QTR', 'YEAR', 'HOUR', 'MINUTE', 'SECOND'.

[!IMPORTANT] INTCK does not count the number of complete elapsed periods; it counts how many discrete interval boundaries (e.g., midnight for days, January 1 for years, first of the month for months) lie between start-date and end-date.

data work.intck_demo;
    d1 = '31DEC2025'd;
    d2 = '01JAN2026'd;
    
    /* Only 1 day has elapsed, but a Year boundary was crossed! */
    years_crossed  = intck('YEAR', d1, d2);   /* Returns 1 */
    months_crossed = intck('MONTH', d1, d2);  /* Returns 1 */
    days_crossed   = intck('DAY', d1, d2);    /* Returns 1 */
run;

To count discrete intervals using continuous boundaries (exact elapsed duration), SAS 9.4 allows passing 'CONTINUOUS' or 'C' as the fourth argument:

/* Continuous method checks full 365-day duration */
actual_years = intck('YEAR', d1, d2, 'C'); /* Returns 0 */

4. Date Adjustments with INTNX

The INTNX function advances or increments a SAS date, time, or datetime value by a specified number of intervals and aligns the resulting value within that interval.

Syntax: INTNX(interval,start-date,increment,<alignment>)\text{Syntax: } \text{INTNX}('\textit{interval}', \textit{start-date}, \textit{increment}, <'\textit{alignment}'>)

Alignment Options:

  • 'BEGINNING' or 'B': Aligns the date to the first day of the target interval (default).
  • 'MIDDLE' or 'M': Aligns the date to the midpoint of the target interval.
  • 'END' or 'E': Aligns the date to the last day of the target interval.
  • 'SAME' or 'S': Preserves the same relative day position within the target interval.
data work.intnx_demo;
    start = '15MAY2026'd;
    
    next_month_beg  = intnx('MONTH', start, 1, 'B'); /* 01JUN2026 */
    next_month_end  = intnx('MONTH', start, 1, 'E'); /* 30JUN2026 */
    next_month_same = intnx('MONTH', start, 1, 'S'); /* 15JUN2026 */
    prev_qtr_end    = intnx('QTR', start, -1, 'E');  /* 31MAR2026 */
run;

5. Precise Age & Year Calculation: YRDIF

The YRDIF function calculates the exact fractional difference in years between two SAS dates according to a specified day-count basis.

Syntax: YRDIF(start-date,end-date,basis)\text{Syntax: } \text{YRDIF}(\textit{start-date}, \textit{end-date}, '\textit{basis}')

Common basis standards include 'ACT/ACT' (actual days / actual year length), '30/360', and 'ACT/360'.

data work.yrdif_demo;
    dob = '15MAY1990'd;
    ref = '15NOV2026'd;
    age = yrdif(dob, ref, 'ACT/ACT'); /* Returns 36.5041... */
run;
Test Your Knowledge

What internal numeric value is stored by SAS for the date January 1, 1960?

A
B
C
D
Test Your Knowledge

Consider the following SAS DATA step: data work.test_intck; dt1 = '31DEC2025'd; dt2 = '01JAN2026'd; num_years = intck('YEAR', dt1, dt2); run; What is the value of NUM_YEARS?

A
B
C
D
Test Your Knowledge

A SAS programmer needs to calculate the last day of the current month based on a variable DATE_VAL. Which function call produces this result?

A
B
C
D
Test Your Knowledge

Which SAS statement correctly creates a SAS date variable named EVENT for October 31, 2026?

A
B
C
D
Test Your Knowledge

A data set contains ORDER_DATE, a SAS date value. A programmer needs a new numeric variable QUARTER holding the calendar quarter (1, 2, 3, or 4) in which each order was placed. Which assignment statement produces that value?

A
B
C
D