BookmarkSubscribeRSS Feed
IrishGuy
Calcite | Level 5
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?
8 REPLIES 8
GertNissen
Barite | Level 11
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 🙂
IrishGuy
Calcite | Level 5
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.
Peter_C
Rhodochrosite | Level 12
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
IrishGuy
Calcite | Level 5
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.)
Cynthia_sas
SAS Super FREQ
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]
IrishGuy
Calcite | Level 5
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.
deleted_user
Not applicable
Guy

the time. format shows more than 24 hrs

PeterC
IrishGuy
Calcite | Level 5
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.

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 8 replies
  • 1878 views
  • 0 likes
  • 5 in conversation