Skip to Main Content

Using dates | SAS Learning Modules

1. Reading dates in data

This module will show how to read date variables, use
date functions, and use date display formats in SAS. You are assumed to be familiar with
data
steps for reading data into SAS, and assignment statements for computing new variables. If
any of the concepts are completely new, you may want to look at For more information below for directions to other learning modules. The
data file used in the first example is presented next.

John  1 Jan 1960
Mary 11 Jul 1955
Kate 12 Nov 1962
Mark  8 Jun 1959

The program below reads the data and creates a temporary
data file called dates.  Note that the dates are read in the
data step, and the format date11. is used to read the date.

DATA dates;
   INPUT  name $ 1-4 @6 bday date11.;
CARDS;
John  1 Jan 1960
Mary 11 Jul 1955
Kate 12 Nov 1962
Mark  8 Jun 1959
;
RUN;
PROC PRINT DATA=dates;
RUN; 

The output of the proc print is
presented below.  Compare the dates in the data to the values of bday.
Note that for John the date is 1 Jan 1960 and the value
for bday is 0.  This is because dates are stored
internally in SAS as the number of days from Jan 1,1960. Since Mary was
born before 1960 the value of bday for her is negative
(-1635).

OBS    NAME     BDAY

 1     John        0
 2     Mary    -1635
 3     Kate     1046
 4     Mark     -207

In order to see the dates in a way that we understand
you would have to format the output. We use the date9. format to see
dates in the form ddmmmyyyy. This is specified on a format
statement.

 PROC PRINT DATA=dates;
   FORMAT bday date9. ;
RUN;  

Here is the output produced by the proc print
statement above.

OBS    NAME         BDAY

 1     John    01JAN1960
 2     Mary    11JUL1955
 3     Kate    12NOV1962
 4     Mark    08JUN1959

Let’s look at the following data. At first glance it
looks like the dates are so different that they couldn’t be read. They do have two things
in common:

1) they all have numeric months,
2) they all are ordered month, day, and then year.

John 1 1 1960
Mary 07/11/1955
Joan 07-11-1955
Kate 11.12.1962
Mark 06081959

These dates can be read with the same format, mmddyy11.
An example of the use of that format in a data step follows.

DATA dates;
   INPUT  name $ 1-4 @6 bday mmddyy11.;
CARDS;
John 1 1 1960
Mary 07/11/1955
Joan 07-11-1955
Kate 11.12.1962
Mark 06081959
;
RUN;
PROC PRINT DATA=dates;
   FORMAT bday date9. ;
RUN;

The results of the above proc print
show that all of the dates are read correctly.

OBS    NAME         BDAY

 1     John    01JAN1960
 2     Mary    11JUL1955
 3     Joan    11JUL1955
 4     Kate    12NOV1962
 5     Mark    08JUN1959

There is a wide variety of formats available
for use in reading dates into SAS. The following is a sample of some of those formats.

Informat   Description        Range   Width    Sample
--------   -----------        -----   -------  ------
JULIANw.   Julian date        5-32    5        65001
           YYDDD
DDMMYYw.   date values        6-32    6        14/8/1963
MONYYw.    month and year     5-32    5        JUN64
YYMMDDw.   date values        6-32    8        65/4/29
YYQw.      year and quarter   4-32    4        65Q1

Consider the following data in which the order is month,
year and day.

 7 1948 11
 1 1960  1
10 1970 15
12 1971 10  

You may read these data with each portion of the date in
a separate variable as in the data step that follows.

DATA dates;
   INPUT  month 1-2 year 4-7 day 9-10;
   bday=MDY(month,day,year);
CARDS;
 7 1948 11
 1 1960  1
10 1970 15
12 1971 10
;
RUN;

PROC PRINT DATA=dates;
   FORMAT bday date9. ;
RUN;

Notice the function mdy(month,day,year)
in the data step. This function is used to create a date value from the
individual components. The result of the proc print follows.

OBS  MONTH  YEAR  DAY       BDAY

 1      7   1948   11  11JUL1948
 2      1   1960    1  01JAN1960
 3     10   1970   15  15OCT1970
 4     12   1971   10  10DEC1971

2. Two digit dates

Consider the following data, which are the same as above
except that only two digits are used to signify the year, and year appears last.

 7 11 18
 7 11 48
 1  1 60
10 15 70
12 10 71

Reading the data is the same as we just did.

DATA dates;
   INPUT  month day year ;
   bday=MDY(month,day,year);
CARDS;
 7 11 18
 7 11 48
 1  1 60
10 15 70
12 10 71
;
RUN;

PROC PRINT DATA=dates;
   FORMAT bday date9. ;
RUN;

The results of the proc print are shown
below.

OBS  MONTH  DAY    YEAR         BDAY

 1      7    11     18     11JUL1918
 2      7    11     48     11JUL1948
 3      1     1     60     01JAN1960
 4     10    15     70     15OCT1970
 5     12    10     71     10DEC1971

Two digit years work here because SAS assumes a cutoff (yearcutoff)
before which value two digit years are interpreted as the year 2000 and above
and after which they are interpreted as 1999 and below. The default
yearcutoff
differs for different versions of SAS:

SAS 6.12 and before (YEARCUTOFF=1900)
SAS 7 and 8         (YEARCUTOFF=1920)

The options statement in the program
that follows changes the yearcutoff value to 1920. This
causes in two digit years lower than 20 to be read as after the year
2000.
Running the same program then will yield different results when this option is set.

OPTIONS YEARCUTOFF=1920;

DATA dates;
   INPUT  month day year ;
   bday=MDY(month,day,year);
CARDS;
 7 11 18
 7 11 48
 1  1 60
10 15 70
12 10 71
;
RUN;

PROC PRINT DATA=dates;
   FORMAT bday date9. ;
RUN;

The results of the proc print are shown
below. The first observation is now read as occurring in 2018 instead of 1918.

OBS    MONTH    DAY    YEAR         BDAY

 1        7      11     18     11JUL2018
 2        7      11     48     11JUL1948
 3        1       1     60     01JAN1960
 4       10      15     70     15OCT1970
 5       12      10     71     10DEC1971

3. Computations with elapsed dates

SAS date variables make computations
involving dates very convenient. For example, to calculate everyone’s age on
January 1, 2000 use the following conversion in the data
step
.

 age2000=(mdy(1,1,2000)-bday)/365.25 ;  

The program with this calculation in context
follows.

OPTIONS YEARCUTOFF=1900; /* sets the cutoff back to the default */

DATA dates;
   INPUT  name $ 1-4 @6 bday mmddyy11.;
   age2000 = (MDY(1,1,2000)-bday)/365.25 ;
CARDS;
John 1 1 1960
Mary 07/11/1955
Joan 07-11-1955
Kate 11.12.1962
Mark 06081959
;
RUN;

PROC PRINT DATA=dates;
   FORMAT bday date9. ;
RUN;

The results of the proc print are shown
below.  The variable AGE2000 now contains the age in years as of January 1, 2000.

OBS    NAME         BDAY    AGE2000

 1     John    01JAN1960    40.0000
 2     Mary    11JUL1955    44.4764
 3     Joan    11JUL1955    44.4764
 4     Kate    12NOV1962    37.1362
 5     Mark    08JUN1959    40.5667

4. Other useful date functions

There are a number of useful functions for use with date variables. The following is a list of
some of those functions.

Function   Description             Sample
--------   ---------------------   -----------------
month()    Extracts Month          m=MONTH(bday);
day()      Extracts Day            d=DAY(bday) ;
year()     Extracts Year           y=YEAR(bday);
weekday()  Extracts Day of Week    wk_d=WEEKDAY(bday);
qtr()      Extracts Quarter        q=QTR(bday);

The following program demonstrates the use of these
functions.

DATA dates;
   INPUT  name $ 1-4 @6 bday mmddyy11.;
    m=MONTH(bday);
    d=DAY(bday) ;
    y=YEAR(bday);
    wk_d=WEEKDAY(bday);
    q=QTR(bday);
CARDS;
John 1 1 1960
Mary 07/11/1955
Joan 07-11-1955
Kate 11.12.1962
Mark 06081959
;
RUN;

PROC PRINT DATA=dates;
   VAR bday m d y;
   FORMAT bday date9. ;
RUN;

PROC PRINT DATA=dates;
   VAR bday wk_d q;
   FORMAT bday date9. ;
RUN;

The proc print results are
shown below. The new variables contain the month, day, year, day of the week and quarter.

OBS         BDAY     M     D      Y

 1     01JAN1960     1     1    1960
 2     11JUL1955     7    11    1955
 3     11JUL1955     7    11    1955
 4     12NOV1962    11    12    1962
 5     08JUN1959     6     8    1959

OBS         BDAY    WK_D    Q

 1     01JAN1960      6     1
 2     11JUL1955      2     3
 3     11JUL1955      2     3
 4     12NOV1962      2     4
 5     08JUN1959      2     2

5. Summary

6. Problems to look out for

7. For more information