I’m trying to create a variable corresponding to the duration in days between two datetime variables START and END which are in $N8601E. format displayed as yyyy-mm-ddThh:mm in my original dataset.
I have tried the Call is8601_Convert routine but my server crashes every time I run the code below.
data want;
set have;
length DURATION $16;
call is8601_convert('dt/dt','du', START, END, DURATION);
format DURATION $n8601e.;
run;
If I omit the line length TRTDURD $16; the variable DURATION corresponds to values that I can’t make sense of as shown below.
START END DURATION
2011-11-21T11:15 2012-02-08T08:15 32562000
2012-04-13T11:00 2012-07-05T10:00 7081200
2012-04-16T09:40 2012-07-04T05:40 6724800
Any ideas on how to fix this to get the Duration variables displaying a Number of days (and another variable displaying the PnYnMnD format) would be greatly appreciated.
I had no success with both approaches. I believe my problem lies in the format of the START and END variables which Proc Content indicates are in $N8601E. format. When I run the following code, I get errors stating Variables "START" (and "END") has already been defined as a numeric. I tried changing the format of START and END but I always get the same error. If I try changing the format of the START and END to YYMMDD. or any Numeric format, the values just disappear. Nevertheless, this code works if I use date variables with original format YYMMDD. in place of START and END.
data want;
length DURATION $16;
call is8601_convert('dt/dt','du',START,END,DURATION);
format DURATION $N8601E.;
set have;
run;
Anyways, after trying different things, I found that the following code works perfectly with START and END in $N8601E. format even though I thought that using the INPUT function, the format indicated should be the format of the original variable, not the new variable... anyway, this works...
data want;
set have;
STARTN=input(START, IS8601DA.);
ENDN=input(END, IS8601DA.);
DURATION=DATDIF(STARTN,ENDN,'actual');
run;
output:
START END DURATION
2011-11-21T11:15 2012-02-08T08:15 79
2011-12-14T11:35 2012-03-05T09:45 82
2012-04-13T11:00 2012-07-05T10:00 83
2012-04-16T09:40 2012-07-04T05:40 79
Are you attempting this in another database?
Your format information, if correct tells me that your variables are currently SAS datetime values. To find intervals between them use the INTCK function:
Duration = intck('hour',start, end);
You may need to provide a format for the result if you want to something other than the number of seconds.
Note that with datetimes to get DATE based intervals such as days, weeks, months that you specify an interval ending in DT such as
Duration = intck('daydt',start, end);
When DURATION is numeric the value returned is number of seconds in the duration. However I don't understand why it does't work for you when DURATION is character as that does work for me.
data want;
input (start end)(:e8601dt.);
length DURATION $16;
call is8601_convert('dt/dt','du', START, END, DURATION);
call is8601_convert('dt/dt','du', START, END, DURATION2);
format DURATION $n8601e.;
format start end e8601dt.;
format duration2 datetime20.;
cards;
2011-11-21T11:15:00 2012-02-08T08:15:00
2012-04-13T11:00:00 2012-07-05T10:00:00
2012-04-16T09:40:00 2012-07-04T05:40:00
;;;;
run;
proc print;
run;
I had no success with both approaches. I believe my problem lies in the format of the START and END variables which Proc Content indicates are in $N8601E. format. When I run the following code, I get errors stating Variables "START" (and "END") has already been defined as a numeric. I tried changing the format of START and END but I always get the same error. If I try changing the format of the START and END to YYMMDD. or any Numeric format, the values just disappear. Nevertheless, this code works if I use date variables with original format YYMMDD. in place of START and END.
data want;
length DURATION $16;
call is8601_convert('dt/dt','du',START,END,DURATION);
format DURATION $N8601E.;
set have;
run;
Anyways, after trying different things, I found that the following code works perfectly with START and END in $N8601E. format even though I thought that using the INPUT function, the format indicated should be the format of the original variable, not the new variable... anyway, this works...
data want;
set have;
STARTN=input(START, IS8601DA.);
ENDN=input(END, IS8601DA.);
DURATION=DATDIF(STARTN,ENDN,'actual');
run;
output:
START END DURATION
2011-11-21T11:15 2012-02-08T08:15 79
2011-12-14T11:35 2012-03-05T09:45 82
2012-04-13T11:00 2012-07-05T10:00 83
2012-04-16T09:40 2012-07-04T05:40 79
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
Need to connect to databases in SAS Viya? SAS’ David Ghan shows you two methods – via SAS/ACCESS LIBNAME and SAS Data Connector SASLIBS – in this video.
Find more tutorials on the SAS Users YouTube channel.