Help using Base SAS procedures

Create Format to Display Time Interval

Reply
Occasional Contributor
Posts: 16

Create Format to Display Time Interval

Hi there. I can find plenty of stuff on displaying date/time values but not much on displaying time interval values. All the formats seem to be about points in time.

I have a numeric field holding a time interval in seconds .e.g. 3600. This is a time interval and not a point in time 3600 seconds after 1 Jan 1960 so the usual time formats don't seem to apply.

I want to display this as xx hours yy mins zz secs
e.g. 3600 seconds will display as 1 hours 0 mins 0 secs
e.g. 360000 seconds will display as 100 hours 0 mins 0 secs
e.g. 360065 seconds will display as 100 hours 1 mins 5 secs

I don't see how to do this with picture etc in a format. Ok it looks possible to convert seconds to just hours or just minutes but to display like this....

I imagine this is a common enough requirement so is there a format out there I am missing. Or any ideas for creating one?
SAS Employee
Posts: 166

Re: Create Format to Display Time Interval

I have been boing some experiments...

1)
The first 'solution' I can think of is this hack (not pretty)
[pre]
data time;
input seconds;
h=hour(seconds);
m=minute(seconds);
s=second(seconds);
test = cat(scan(put(seconds,hhmm6.0),1,':'),' hours ',m,' mins ',s,' secs');
put (_all_)(=/);
datalines;
3600
360000
360065
;
run;
[/pre]

2)
And I can't think of how to do it with a picture format. The Hour directive will only display 0-23.
[pre]
proc format;
picture intervalX
low-high = '%H hours %M mins %S secs' (datatype=time);
run;

data time;
input seconds;
put seconds intervalX.;
datalines;
3600
360000
360065
;
run;
[/pre]

3)
Finally the following example - Generate a dataset with your range of values and use this as an input for your format.
[pre]
data interval;
fmtname='interval';
do i= 1 to 360065;
start = i;
label= cat(scan(put(i,hhmm6.0),1,':'),' hours ',minute(i),' mins ',second(i),' secs');
output;
end;
run;

proc format cntlin=interval;
run;

data time;
input seconds;
put seconds interval.;
datalines;
3600
360000
360065
;
run;
[/pre]

And your right - Strange that SAS does not have a format for this - perhaps in 9.21 :-)
Occasional Contributor
Posts: 16

Re: Create Format to Display Time Interval

1 & 3 are great solutions. 3. is perfect because I can re-use that format wherever I need. One small change: I had to replace "put seconds interval.;" with
"format seconds interval.;" to pick up the new format.

Thanks. Would have taken me days to get that.
Valued Guide
Posts: 2,175

Re: Create Format to Display Time Interval

just use the time format.
Here is an example (tested in SAS9.1.3 on zOS)[pre]
34 %let fromdt= 12Oct2008:0:0:0 ;
35 %let TOdt= 23Oct2008:14:15:20.123 ;
36 %put duration = %sysfunc( range( "&fromDT"dt, "&toDT"dt ), time14 );
duration = 278:15:20 [/pre]

The RANGE() function has calculated the difference between two datetime values, and %SYSFUNC() formatted the result using the TIME. format

Internally, datetime values are a (real) number of seconds since the beginning of 1Jan1960, so the difference is a (real) number of seconds.


does this not show that the TIME format provides the duration format required?

PeterC
Occasional Contributor
Posts: 16

Re: Create Format to Display Time Interval

Ah! That works pretty well. The only thing is that the output looks obscure to some of my users so explicitly showing hours, mins, seconds means they know the precise meaning of the field. All the existing formats like that seem to revert to the 24 hour clock so won't hold values over 24 hours. (I could definitely be wrong though. Could be a format out there.)
SAS Super FREQ
Posts: 8,781

Re: Create Format to Display Time Interval

Hi:
Combining the RANGE/TIME14 approach with a bit of character function magic might give you what you want...since TIME14 will result in 0 hours, etc. (I didn't use macro variables in the data step because I wanted to show 2 obs with diff values for duration and it seems you'll probably be doing this in a data step program because there really isn't a format that will do exactly what you want. You'll have to construct your own character string.)

cynthia
[pre]
data testdur;
infile datalines;
input fromdt : datetime. todt : datetime.;

duration = range(fromdt, todt);
textstr = put(duration,time14.);
newdur = scan(textstr,1,':')|| ' hours '||
scan(textstr,2,':')|| ' minutes '||
scan(textstr,3,':')|| ' seconds';
output;
return;
datalines;
12Oct2008:0:0:0 23Oct2008:14:15:20.123
12Oct2008:0:0:0 12Oct2008:0:12:17.456
;
run;

proc print data=testdur;
run;
[/pre]
Occasional Contributor
Posts: 16

Re: Create Format to Display Time Interval

Thanks Cynthia. I do want to keep the field numeric though so the users can manipulate it and the re-use of a format is handy so went with the solution to create the format through cntlin. But this is brilliant. Learned more from this thread than I did in weeks programming by myself.
N/A
Posts: 0

Re: Create Format to Display Time Interval

Guy

the time. format shows more than 24 hrs

PeterC
Occasional Contributor
Posts: 16

Re: Create Format to Display Time Interval

Yeah, I finally realised that my assumption about the time format was wrong after looking at the last post! But still had to generate own format as per instructions above to get the one I wanted that showed the units of measurement more clearly and was still numeric.
Ask a Question
Discussion stats
  • 8 replies
  • 228 views
  • 0 likes
  • 5 in conversation