22.2 - SAS Date Functions

The date functions that are available in SAS can be used to:

  • create date values
  • take apart date values
  • massage date values (what??!)
  • calculate intervals

For no particular reason, we'll look at them in that order.

Using functions to create date values Section

The functions that can be used to create date values include:

  • date( ) returns today's date as a SAS date value
  • today( ) returns today's date as a SAS date value
  • mdy(m,d,y) returns a SAS date value from the given month (m), day (d), and year (y) values
  • datejul(juldate) converts a Julian date (juldate) to a SAS date value
  • yyq(y, q) returns a SAS date value from the given year (y) and quarter (q) 1, 2, 3, or 4

The date( ) and today( ) functions are equivalent. That is, they both return the current date as defined as the date on which the SAS program is executed. You don't need to put anything in between the parentheses for those two functions.

A Julian date is defined in SAS as a date in the form yyddd or yyyyddd, where yy or yyyy is a two-digit or four-digit integer that represents the year, and ddd is the number of the day of the year. The value of ddd must be between 001 and 365 (or 366 for a leap year). So, for example, the SAS Julian date for January 21, 2008 is 2008021.

Let's look at an example in which these five functions are used.

Example 22.6

The following SAS program creates a temporary SAS data set called createdates that contains six date variables. The variables current1 and current2 are assigned the current date using the date( )and today( ) functions. The variable current3 is assigned the 95th day of the 2008 year using the datejul( ) function. The variables current4 and current5 are assigned the date April 4th, 2008 using the mdy( ) function. And, the variable current6 is assigned the date April 1st, 2008 using the yyq( ) function.

DATA createdates;
    current1= date();
    current2 = today();
    current3 = datejul(2008095);
    mon = 4; day = 4; year = 2008;
    current4 = mdy(mon, day, year);
    current5 = current4;
    current6 = yyq(2008, 2);
    format current1 current2 current3 current5 current6 date9.;
RUN;

PROC PRINT data=createdates;
    title 'The createdates data set';
    var current1 current2 current3 current4 current5 current6;
RUN;

The createdates data set
Obscurrent1current2current3current4current5current6
120SEP202320SEP202304APR20081762604APR200801APR2008

First, review the program to make sure that you understand how to use each of the five functions. Note, for example, that to tell SAS to determine the SAS date value of the 95th day of the 2008 year, you have to input 2008095 into the datejul( ) function. If you instead input 200895 into the datejul( ) function, SAS reports that you've provided an invalid argument to the datejul( ) function and therefore sets current3 to missing. Also, note that current5 is just the formatted version of the unformatted current4 variable. When you are satisfied that you understand the five functions, launch and run  the SAS program. Review the output to convince yourself that createdates does indeed contain the six date variables as described.

Using functions to take apart date values Section

The functions that can be used to take apart date values include:

  • day(date) returns the day of the month from a SAS date value (date)
  • month(date) returns the month from a SAS date value (date)
  • year(date) returns the year from a SAS date value (date)

The date can be specified either as a variable name or as a SAS date constant. Otherwise, fairly self-explanatory! Let's take a look at an example.

Example 22.7

The following SAS program uses the day( ), month( ), and year( ) functions to extract the month, day, and year from the wt_date variable:

DATA takeapart;
    input subj 1-4 l_name $ 18-23 weight 30-32
    	+1 wt_date mmddyy8. @43 b_date mmddyy8.;
    wt_mo = month(wt_date);
    wt_day = day(wt_date);
    wt_yr = year(wt_date);
    format wt_date b_date date9.;
	DATALINES;
1024 Alice       Smith  1 65 125 12/1/05  01/01/60
1167 Maryann     White  1 68 140 12/01/05 01/01/59
1168 Thomas      Jones  2    190 12/2/05  06/15/60
1201 Benedictine Arnold 2 68 190 11/30/05 12/31/60
1302 Felicia     Ho     1 63 115 1/1/06   06/15/58
;
 
RUN;
 
PROC PRINT data=takeapart;
    title 'The dissected weight dates';
	var wt_date wt_mo wt_day wt_yr;
RUN;

The dissected weight dates
Obswt_datewt_mowt_daywt_yr
101DEC20051212005
201DEC20051212005
302DEC20051222005
430NOV200511302005
501JAN2006112006

First, review the program to make sure that you understand how to use each of the three functions. Then, launch and run the SAS program, and review the output to convince yourself that the program does as claimed.

Using functions to massage date values Section

Okay, here's that section with the intriguing title. The functions that can be used to massage date values include:

  • juldate(date) returns the Julian date in yyddd format from a SAS date value (date)
  • juldate7(date) returns the Julian date in yyyyddd format from a SAS date value (date)
  • qtr(date) returns the quarter of the year from a SAS date value (date) (1 = first three months, 2 = second three months, 3 = third three months, or 4 = last three months)
  • weekday(date) returns the number of the day of the week from a date value (date) (1 = Sunday, 2 = Monday, ..., and 7 = Saturday)

Again, the date can be specified either as a variable name or as a SAS date constant. And, a Julian date in SAS is defined as a date in the form yyddd or yyyyddd, where yy or yyyy is a two-digit or four-digit integer that represents the year and ddd is the number of the day of the year (between 001 and 365 (or 366 for a leap year)).

Let's look at an example in which these four functions are used.

Example 22.8

The following SAS program contains four assignment statements that "massage" the wt_date variable. The variable wt_jul1 is assigned the SAS Julian date in yyddd format. The variable wt_jul2 is assigned the SAS Julian date in yyyyddd format. The variable wt_qtr is assigned the quarter in which the wt_date occurs, and the variable wt_day is assigned the weekday on which the wt_date occurs:

DATA massaged;
	input subj 1-4 l_name $ 18-23 weight 30-32
    	+1 wt_date mmddyy8. @43 b_date mmddyy8.;
    wt_jul1 = juldate(wt_date);
    wt_jul2 = juldate7(wt_date);
    wt_qtr = qtr(wt_date);
    wt_day = weekday(wt_date);
    format wt_date b_date date9.;
    DATALINES;
1024 Alice       Smith  1 65 125 12/1/05  01/01/60
1167 Maryann     White  1 68 140 12/01/05 01/01/59
1168 Thomas      Jones  2    190 12/2/05  06/15/60
1201 Benedictine Arnold 2 68 190 11/30/05 12/31/60
1302 Felicia     Ho     1 63 115 1/1/06   06/15/58
;

RUN;

PROC PRINT data = massaged;
	title 'The massaged data set';
    var wt_date wt_jul1 wt_jul2 wt_qtr wt_day;
RUN;

The massaged data set
Obswt_datewt_jul1wt_jul2wt_qtrwt_day
101DEC20055335200533545
201DEC20055335200533545
302DEC20055336200533646
430NOV20055334200533444
501JAN20066001200600111

First, review the program to make sure that you understand how to use each of the four functions. Then, launch and run the SAS program, and review the output to convince yourself that the program does as claimed.

Using functions to calculate intervals Section

The functions that can be used to calculate intervals include:

  • yrdif(startdate, enddate, 'method') returns the difference in years between two SAS date values (startdate, enddate) using one of four methods ('method')
  • datdif(startdate, enddate, 'method') returns the difference in days between two SAS date values (startdate, enddate) using one of four methods ('method')
  • intck('interval', fromdate, todate) returns the number of time intervals ('interval') that occur between two dates (fromdate, todate)
  • intnx('interval', date, increment) applies multiples (increment) of a given interval ('interval') to a date value (date) and returns the resulting value, and hence can be used to identify past or future days, weeks, months, and so on

We'll take a look at five examples here. The first one uses the yrdif( ) and datdif( ) functions, the next three use the intck( ) function, and the last one uses the intnx( ) function.

Example 22.9

The following SAS program uses the yrdif( ) function to calculate the difference between the subject's birth date (b_date) and first weight date (wt_date1) in order to determine the subject's age. And, the datdif( ) function is used to calculate days, the difference between the subject's first (wt_date1) and second (wt_date2) weight dates:

DATA diet;
	input subj 1-4 l_name $ 18-23 weight 30-32
        +1 wt_date1 mmddyy8. @43 wt_date2 mmddyy8. @52 
    	b_date mmddyy8.;
    age  = yrdif(b_date, wt_date1, 'act/act');
    days = datdif(wt_date1, wt_date2, 'act/act');
    format wt_date1 wt_date2 b_date date9.  age 4.1;
	DATALINES;
1024 Alice       Smith  1 65 125 12/1/05  03/04/06 01/01/60
1167 Maryann     White  1 68 140 12/01/05 03/07/06 01/01/59
1168 Thomas      Jones  2    190 12/2/05  3/30/06  06/15/60
1201 Benedictine Arnold 2 68 190 11/30/05 2/27/06  12/31/60
1302 Felicia     Ho     1 63 115 1/1/06   4/1/06   06/15/58
	;
RUN;
 
PROC PRINT data=diet;
    TITLE "The calculation of subject's age";
	var subj b_date wt_date1 age;
RUN;
 
PROC PRINT data=diet;
    TITLE 'The calculation of days between weighings';
	var subj wt_date1 wt_date2 days;
RUN;

The calculation of subject's age
Obssubjb_datewt_date1age
1102401JAN196001DEC200545.9
2116701JAN195901DEC200546.9
3116815JUN196002DEC200545.5
4120131DEC196030NOV200544.9
5130215JUN195801JAN200647.5

The calculation of days between weighings
Obssubjwt_date1wt_date2days
1102401DEC200504MAR200693
2116701DEC200507MAR200696
3116802DEC200530MAR2006118
4120130NOV200527FEB200689
5130201JAN200601APR200690

Review the assignment statement that is used to calculate the values for the variable age. The first and second arguments of the yrdif( ) function tell SAS, respectively, the start and end date of the desired interval. Here, the start date is b_date and the end date is wt_date1. The third argument of the yrdif( ) function, which must be enclosed in single quotes, tells SAS how to calculate the difference. Here, 'act/act' tells SAS to calculate the difference using the actual number of years between the two dates. The four possible methods in calculating the number of years between two dates using the yrdif( ) function are:

  • 'act/act' uses the actual number of days and years between two dates
  • '30/360' specifies a 30-day month and a 360-day year
  • 'act/360' uses the actual number of days between dates in calculating the number of years (calculated by the number of days divided by 360)
  • 'act/365' uses the actual number of days between dates in calculating the number of years (calculated by the number of days divided by 365)

The 'act/act' method is the method that most people would consider to be the most accurate. The other methods are methods that are sometimes used by accountants.

Now, review the assignment statement that is used to calculate the values for the variable days. The first and second arguments of the datdif( ) function tell SAS, respectively, the start and end date of the desired interval. Here, the start date is wt_date1 and the end date is wt_date2. The third argument of the datdif( ) function, which must be enclosed in single quotes, tells SAS how to calculate the difference. Here, 'act/act' tells SAS to calculate the difference using the actual number of days between the two dates. The two possible methods for calculating the number of days between two dates using the datdif( ) function are:

  • 'act/act' uses the actual number of days and years between two dates
  • '30/360' specifies a 30-day month and a 360-day year

Again, the 'act/act' method is the method that most people would consider to be the most accurate. The other method is a method that is sometimes used by accountants.

When you are satisfied that you understand the two functions, launch and run the SAS program. Review the output to convince yourself that age and days are indeed calculated as described.

Example 22.10

Recall that the intck( ) function returns the number of time intervals, such as the number of days or years, that occur between two dates. The following SAS program is identical to the previous program, except here the subjects' ages at their first weigh-in are determined using both the yrdif( ) and intck( ) functions to get age_yrdif and age_intchk, respectively. Similarly, the number of days between the subjects' two weigh-ins is determined using both the datdif( ) and intck( ) functions to get days_datdif and days_intchk, respectively:

DATA diet;
	input subj 1-4 l_name $ 18-23 weight 30-32
    	+1 wt_date1 mmddyy8. @43 wt_date2 mmddyy8. @52 
        b_date mmddyy8.;
    age_yrdif  = yrdif(b_date, wt_date1, 'act/act');
    age_intck = intck('year', b_date, wt_date1);
    days_datdif = datdif(wt_date1, wt_date2, 'act/act');
    days_intck = intck('day', wt_date1, wt_date2);
    format wt_date1 wt_date2 b_date date9.  age 4.1;
	DATALINES;
1024 Alice       Smith  1 65 125 12/1/05  03/04/06 01/01/60
1167 Maryann     White  1 68 140 12/01/05 03/07/06 01/01/59
1168 Thomas      Jones  2    190 12/2/05  3/30/06  06/15/60
1201 Benedictine Arnold 2 68 190 11/30/05 2/27/06  12/31/60
1302 Felicia     Ho     1 63 115 1/1/06   4/1/06   06/15/58
  ;
RUN;

PROC PRINT data=diet;
	TITLE "The calculation of subject's age";
    var subj b_date wt_date1 age_yrdif age_intck;
RUN;

PROC PRINT data=diet;
	TITLE 'The calculation of days between weighings';
    var subj wt_date1 wt_date2 days_datdif days_intck;
RUN;

The calculation of subject's age
Obssubjb_datewt_date1age_yrdifage_intck
1102401JAN196001DEC200545.915145
2116701JAN195901DEC200546.915146
3116815JUN196002DEC200545.464345
4120131DEC196030NOV200544.915145
5130215JUN195801JAN200647.547948

The calculation of days between weighings
Obssubjwt_date1wt_date2days_datdifdays_intck
1102401DEC200504MAR20069393
2116701DEC200507MAR20069696
3116802DEC200530MAR2006118118
4120130NOV200527FEB20068989
5130201JAN200601APR20069090

Review the assignment statement that is used to calculate the values for the variable age_intck. The first argument of the intck( ) function, which must appear in single quotes, tells SAS what time interval you are interested in counting. Although there are other intervals available, the most commonly used intervals include 'day', 'weekday', 'week', 'month', 'qtr', and 'year'. The second and third arguments of the intck( ) function tell SAS, respectively, the start and end date of the desired interval. Here, the start date is b_date, the end date is wt_date1, and the time interval is 'year'.

Now, review the assignment statement that is used to calculate the values for the variable days_intck. To calculate days, the start date is wt_date1, the end date is wt_date2, and the time interval is 'day'.

Theoretically, we should expect the yrdif( ) and intck( ) functions to get the same answers for age, and the datdif( ) and intck( ) functions to get the same answers for days. Launch and run  the SAS program, and review the resulting output. Same answers or not? Hmmm ... you should see that the values for days_datdif and days_intck are the same, while the (rounded) values for age_yrdif and age_intck differ.

Why is that the case? It has to do with the fact that the intck( ) function counts intervals from fixed interval beginnings, not in multiples of an interval unit from the startdate value. Partial intervals are not counted. For example, 'week' intervals are counted by Sundays rather than seven-day multiples from the startdate value. 'Month' intervals are counted by the first day of each month, and 'year' intervals are counted from January 1st, not in 365-day multiples from the startdate value.

The next two examples are intended to help you understand how the intck( ) function counts intervals.

Example 22.11

The following SAS program uses the intck( ) function and SAS date constants to determine the number of days, weeks, months, and years between December 31, 2006, and January 1, 2007. It also calculates the number of years (years2) between January 1, 2007 and December 31, 2007, and the number of years (years3) between January 1, 2007 and January 1, 2008:

DATA timeintervals1;
     days = intck('day', '31dec2006'd,'01jan2007'd);
     weeks = intck('week', '31dec2006'd,'01jan2007'd);
     months = intck('month', '31dec2006'd,'01jan2007'd);
     years = intck('year', '31dec2006'd,'01jan2007'd);
     years2 = intck('year', '01jan2007'd, '31dec2007'd);
     years3 = intck('year', '01jan2007'd, '01jan2008'd);
RUN;

PROC PRINT data = timeintervals1;
	TITLE 'Time intervals as calculated by intck function';
RUN;

Time intervals as calculated by intck function
Obsdaysweeksmonthsyearsyears2years3
1101101

First, review the program to make sure that you understand what it is doing. Then, launch and run  the SAS program, and review the output. Are you surprised by any of the results? Let me venture to suggest that you find the results for days, weeks, and years3 to make sense, and the results for months, years, and years2 to be a little odd. Let's focus on the three odd results. In spite of only one day passing between 12/31/2006 and 01/01/2007, SAS assigns the variable months the value 1 because, between 12/31/2006 and 01/01/2007, exactly one first day of the month is crossed (which happens to be January 1st). Similarly, in spite of only one day passing between 12/31/2006 and 01/01/2007, SAS assigns the variable years the value 1 because, between 12/31/2006 and 01/01/2007, exactly one January 1st is crossed. And, in spite of 364 days passing between 01/01/2007 and 12/31/2007, SAS assigns the variable years2 the value 0 because no January 1st is crossed. Now, even though the results for days, weeks, and years3 might make intuitive sense to you, you should still make sure you understand why SAS assigns the values it does here based on how the intck( ) function works.

Example 22.12

In an attempt to explore the intck( ) function further, the following SAS program uses the intck( ) function and SAS date constants to determine the number of days, weeks, weekdays, months, qtrs, and years between March 15, 2007 and March 15, 2008:

DATA timeintervals2;
        days = intck('day', '15mar2007'd,'15mar2008'd);
        weeks = intck('week', '15mar2007'd,'15mar2008'd);
        weekdays = intck('weekday', '15mar2007'd,'15mar2008'd);
        months = intck('month', '15mar2007'd,'15mar2008'd);
        qtrs = intck('qtr', '15mar2007'd,'15mar2008'd);
        years = intck('year', '15mar2007'd,'15mar2008'd);
RUN;
        
PROC PRINT data = timeintervals2;
       TITLE 'Time intervals as calculated by intck function';
RUN;

Time intervals as calculated by intck function
Obsdaysweeksweekdaysmonthsqtrsyears
1366522611241

The main purpose of this program is to illustrate some of the intervals most commonly used in the intck( ) function. First, review the program to make sure that you understand what it is doing. Then, launch and run the SAS program, and review the output. Are you surprised by any of the results? In each case, I think you'll find the results to make intuitive sense.

Example 22.13

Now, suppose that each subject appearing in the diet data set needs to be weighed again in three months. The following SAS program uses the subject's previous weight date (wt_date) and various versions of the intnx( ) function to determine various versions of each subject's next weight date:

DATA diet;
    input subj 1-4 l_name $ 18-23 weight 30-32
		+1 wt_date mmddyy8. @43 b_date mmddyy8.;
    nxdate_b1 = intnx('month', wt_date, 3);
    nxdate_b2 =  intnx('month', wt_date, 3, 'beginning');
    nxdate_m = intnx('month', wt_date, 3, 'middle');
    nxdate_e = intnx('month', wt_date, 3, 'end');
    nxdate_s = intnx('month', wt_date, 3, 'sameday');
    format wt_date b_date nxdate_b1 nxdate_b2 
     	nxdate_m nxdate_e nxdate_s date9.;
	DATALINES;
1024 Alice       Smith  1 65 125 12/1/05  01/01/60
1167 Maryann     White  1 68 140 12/01/05 01/01/59
1168 Thomas      Jones  2    190 12/2/05  06/15/60
1201 Benedictine Arnold 2 68 190 11/30/05 12/31/60
1302 Felicia     Ho     1 63 115 1/1/06   06/15/58
;
RUN;

PROC PRINT data=diet;
	TITLE 'The data set containing next weight dates';
    VAR subj wt_date nxdate_b1 nxdate_b2 
    	nxdate_m nxdate_e nxdate_s;
RUN;

The data set containing next weight dates
Obssubjwt_datenxdate_b1nxdate_b2nxdate_mnxdate_enxdate_s
1102401DEC200501MAR200601MAR200616MAR200631MAR200601MAR2006
2116701DEC200501MAR200601MAR200616MAR200631MAR200601MAR2006
3116802DEC200501MAR200601MAR200616MAR200631MAR200602MAR2006
4120130NOV200501FEB200601FEB200614FEB200628FEB200628FEB2006
5130201JAN200601APR200601APR200615APR200630APR200601APR2006

Let's review the five assignment statements that calculate five versions of the subjects' next weight dates (nxdate_b1, nxdate_b2, nxdate_m, nxdate_e, and nxdate_s). As you can see, SAS is told to use the 'month' interval in each of the calculations. Again, although there are other intervals available, the most commonly used intervals include 'day', 'weekday', 'week', 'month', 'qtr', and 'year'. SAS is also told to use wt_date as the startdate in each of the calculations. And in each case, SAS is told to advance the wt_date by 3 months. Okay, so the only thing that differs between the five calculations are the last (optional) arguments ('beginning', 'middle', 'end', and 'sameday'). These so-called alignment arguments tell SAS to return either the beginning, middle, or end day of the resulting month. If an alignment is not specified, the beginning day is returned by default. If the 'sameday' alignment is specified, SAS of course returns the same number day but shifted by the number of specified intervals.

Let's launch and run the SAS program, and review the output. The dates should be as described. The contents of nxdate_b1 is the same as nxdate_b2, since the beginning day is returned by default. The variable nxdate_m contains the middle day of the resulting month, and nxdate_e contains the end day of the resulting month. And, for four of the subjects, SAS returns the same number day but 3 months in the future. For subject #1201, you would expect SAS to return February 30th, because it is exactly 3 months from November 30th. This illustrates how the intnx( ) function automatically adjusts the date if the resulting date doesn't exist.

Whewww! That does it! Everything you wanted to know about SAS date functions and more. Let's move on and touch a little bit more on reading and displaying dates in SAS.