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;
Obs | current1 | current2 | current3 | current4 | current5 | current6 |
---|---|---|---|---|---|---|
1 | 20SEP2023 | 20SEP2023 | 04APR2008 | 17626 | 04APR2008 | 01APR2008 |
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;
Obs | wt_date | wt_mo | wt_day | wt_yr |
---|---|---|---|---|
1 | 01DEC2005 | 12 | 1 | 2005 |
2 | 01DEC2005 | 12 | 1 | 2005 |
3 | 02DEC2005 | 12 | 2 | 2005 |
4 | 30NOV2005 | 11 | 30 | 2005 |
5 | 01JAN2006 | 1 | 1 | 2006 |
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;
Obs | wt_date | wt_jul1 | wt_jul2 | wt_qtr | wt_day |
---|---|---|---|---|---|
1 | 01DEC2005 | 5335 | 2005335 | 4 | 5 |
2 | 01DEC2005 | 5335 | 2005335 | 4 | 5 |
3 | 02DEC2005 | 5336 | 2005336 | 4 | 6 |
4 | 30NOV2005 | 5334 | 2005334 | 4 | 4 |
5 | 01JAN2006 | 6001 | 2006001 | 1 | 1 |
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;
Obs | subj | b_date | wt_date1 | age |
---|---|---|---|---|
1 | 1024 | 01JAN1960 | 01DEC2005 | 45.9 |
2 | 1167 | 01JAN1959 | 01DEC2005 | 46.9 |
3 | 1168 | 15JUN1960 | 02DEC2005 | 45.5 |
4 | 1201 | 31DEC1960 | 30NOV2005 | 44.9 |
5 | 1302 | 15JUN1958 | 01JAN2006 | 47.5 |
Obs | subj | wt_date1 | wt_date2 | days |
---|---|---|---|---|
1 | 1024 | 01DEC2005 | 04MAR2006 | 93 |
2 | 1167 | 01DEC2005 | 07MAR2006 | 96 |
3 | 1168 | 02DEC2005 | 30MAR2006 | 118 |
4 | 1201 | 30NOV2005 | 27FEB2006 | 89 |
5 | 1302 | 01JAN2006 | 01APR2006 | 90 |
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;
Obs | subj | b_date | wt_date1 | age_yrdif | age_intck |
---|---|---|---|---|---|
1 | 1024 | 01JAN1960 | 01DEC2005 | 45.9151 | 45 |
2 | 1167 | 01JAN1959 | 01DEC2005 | 46.9151 | 46 |
3 | 1168 | 15JUN1960 | 02DEC2005 | 45.4643 | 45 |
4 | 1201 | 31DEC1960 | 30NOV2005 | 44.9151 | 45 |
5 | 1302 | 15JUN1958 | 01JAN2006 | 47.5479 | 48 |
Obs | subj | wt_date1 | wt_date2 | days_datdif | days_intck |
---|---|---|---|---|---|
1 | 1024 | 01DEC2005 | 04MAR2006 | 93 | 93 |
2 | 1167 | 01DEC2005 | 07MAR2006 | 96 | 96 |
3 | 1168 | 02DEC2005 | 30MAR2006 | 118 | 118 |
4 | 1201 | 30NOV2005 | 27FEB2006 | 89 | 89 |
5 | 1302 | 01JAN2006 | 01APR2006 | 90 | 90 |
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;
Obs | days | weeks | months | years | years2 | years3 |
---|---|---|---|---|---|---|
1 | 1 | 0 | 1 | 1 | 0 | 1 |
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;
Obs | days | weeks | weekdays | months | qtrs | years |
---|---|---|---|---|---|---|
1 | 366 | 52 | 261 | 12 | 4 | 1 |
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;
Obs | subj | wt_date | nxdate_b1 | nxdate_b2 | nxdate_m | nxdate_e | nxdate_s |
---|---|---|---|---|---|---|---|
1 | 1024 | 01DEC2005 | 01MAR2006 | 01MAR2006 | 16MAR2006 | 31MAR2006 | 01MAR2006 |
2 | 1167 | 01DEC2005 | 01MAR2006 | 01MAR2006 | 16MAR2006 | 31MAR2006 | 01MAR2006 |
3 | 1168 | 02DEC2005 | 01MAR2006 | 01MAR2006 | 16MAR2006 | 31MAR2006 | 02MAR2006 |
4 | 1201 | 30NOV2005 | 01FEB2006 | 01FEB2006 | 14FEB2006 | 28FEB2006 | 28FEB2006 |
5 | 1302 | 01JAN2006 | 01APR2006 | 01APR2006 | 15APR2006 | 30APR2006 | 01APR2006 |
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.