Dates and times.
As Wayne Finley states in his SUGI25 paper on SAS date and time handling, "The SAS system provides a plethora of methods to handle date and time values."
Along with the plethora of methods is a plethora of papers on the topic. If you want to trick someone into believing that you are clairvoyant, tell them "I predict that there will be a poster or paper about SAS dates and times at next year's SAS Global Forum."
So why blog on this topic? Two reasons:
- to remind everyone that, as Finley (2000) says, "SAS provides a convenient way to declare a date/time constants in programs"
- to describe how you can handle dates and times in the SAS/IML language
The Easy Way to Specify Date and Time Constants
Recall that SAS stores dates and times as numbers, and that formats are used in order to display those numbers as strings such as "21Dec2012."
SAS programmers often use a SAS informat (or the INPUTN function) to read dates and times in the DATA step.
However, in SAS you can also specify a date constant by writing a date (enclosed in single or double quotes) followed by the D symbol. This tells SAS to apply a standard informat and to convert the string to a number. (This syntax is often used in WHERE clause processing.) For example, the following statements are equivalent ways to specify the winter solstice in 2012. They are valid statements in the DATA step, as well as in PROC IML.
proc iml; date = '21Dec2012'd; date2 = inputn("21Dec2012", "date9."); |
In a similar way, you can specify a time in quotes, followed by a T, or a datetime in quotes, followed by a DT:
time = '11:12:23't; datetime = '21Dec2012:11:12:23'dt; print date[format=DATE9.] time[format=TIME8.] datetime[format=DATETIME18.]; |
Using Dates and Times in PROC IML
Many people are familiar with the ideas of specifying date and time literals, since these literals are often encountered in SAS programming with the DATA step. The novelty comes when you combine the literals with vector constructs in the SAS/IML language. For example, you can create a vector of days by using the index creation operator (:):
dates = '21Dec2012'd : '25Dec2012'd; print dates, dates[format=date9.]; |
Another useful trick is to use a date literal in conjunction with the LOC function to subset some data:
use sashelp.air; read all var {date}; close sashelp.air; idx = loc(date < '01Jun1949'd); print idx, (date[idx])[format=date9.]; |
In general, any numeric operation in the SAS/IML language can be performed on dates, because dates are stored as numbers. Of course, if the operation doesn't result in an integer, the result will not itself be a valid date, but that's okay: the SAS date formats will round the number and display a date anyway. For example, the average (mean) value of a bunch of dates is not usually an integer, but you can still ask the DATE9. format to display it as a date:
mean = date[:]; print mean mean[format=date9.]; |
In short, if you remember that dates and times are stored internally as numbers, you can use these values in any SAS/IML numerical computation.
A Small Sample of SAS Date/Time References
To learn more about SAS dates and times, start with the following SAS Global Forum (SUGI) papers:
- Arthur L. Carpenter (2005), "Looking for a Date? A Tutorial on Using SAS Dates and Times"
- Wayne Finley (2000), "A Beginners Guide to SAS Date and Time Handling"
- Derek Morgan (2008), "The Essentials of SAS Dates and Times"
If you crave more, there's an entire book on the topic: Derek P. Morgan (2006), The Essential Guide to SAS Dates and Times
3 Comments
Hi,
I have a matrix where various columns are dates (read in as numeric variables), and want to convert them to SAS dates.
As a test, I tried to convert a column vector, X, with dates (e.g., 20090329) in Proc IML (version 9.22) - (i) date=CHAR(X) and (ii) INPUT(date,yymmdd8.) - but an error results saying that the option "yymmdd8." is invalid.
Any help would be much appreciated! Thanks.
x = {20090329, 20100128, 20110704};
d = inputn(char(x,8), "yymmdd8."); /* use INPUTN */
print d[format=date10.];
Thanks!