BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
eabc0351
Quartz | Level 8

Hello. I am trying to use a time variable in an if-then statement. Please see example code below. The time is formatted as HHMM.

This code is not working due to the timevar portion. I understand that SAS doesn't store time in the formatted form. Is there a way to find out the equivalent values for my hours (i.e. 1,2,3,4...)  and still use this code? Or some better way?

Thank you.

data want; set have;
 if var1=1 and 
(2=<timevar<3 and var2=-.09) 
OR (3=<timevar<4 and var2<=-1.26) 
OR (4=<timevar<5 and var2<=-1.54) 
OR (5=<timevar<6 and var2<=-1.76) 
then varwant=1; else varwant=0;
run;

 

1 ACCEPTED SOLUTION

Accepted Solutions
eabc0351
Quartz | Level 8

@ScottBassyes, some version of that worked for me. Instead of days, I did hours. That provided a numeric variable (best12., not a time format) to use in the previous code. Thank you all!

data test;
   set have;
   select;
      when ("00:00:00"t <= timevar < "01:00:00"t) hours=1;
      when ("01:00:00"t <= timevar< "02:00:00"t) hours=2;
      when ("02:00:00"t <= timevar< "03:00:00"t) hours=3;
      when ("03:00:00"t <= timevar< "04:00:00"t) hours=4;
      otherwise hours=-1;  * representing "unknown" day ;
   end;
run;

View solution in original post

7 REPLIES 7
ballardw
Super User

You probably want to use HOUR(timevar) in some form.

If you have a time like 13:45 then Hour function would return 13

This type of test

3=<timevar<4

would be

3 = hour(timevar)

If the time were 4:00 the hour would be 4. Hour( 3:59:59 ) would return 3.

 

The question might be though do you mean 1AM or 1PM? The SAS Hour function returns 0 to 23. 0 for time from midnight to 00:59:59 in the morning.

eabc0351
Quartz | Level 8

Thank you @ballardw. Actually, my timevar is age in hours for babies. The time goes from birth through 72 hours. Some of the values of my timevar, for example, are 69:15, 34:56, 3:45.

The solution you presented doesn't work for values over 24. Do you have any other suggestions?

Maybe turn the timevar to a numeric variable?  Thank you.

ghosh
Barite | Level 11

The following will give you hours elapsed since birth (20may2019:10:30:00) to current time in hh:mm:ss format

 

data _null_;
hours=(intck('seconds','20may2019:10:30:00'dt,datetime()));
format hours time12.;
put hours;
run;

 

Tom
Super User Tom
Super User

Maybe turn the timevar to a numeric variable?  

Time variables are numeric. They contain seconds.  Unless it is a character variable.  In which case you should convert to a number.

 

ScottBass
Rhodochrosite | Level 12

You didn't specify a "have" dataset, so I can only guess at representative values.

 

Does this work for you?  Adjust as required:

 

data have;
   input time time5.;
   format time time8.;
   datalines;
00:15
13:45
23:59
24:15
28:45
37:10
40:40
50:50
65:55
71:59
73:01
;
run;

data want1;
   set have;
   hour=hour(time);  * so that doesn't work ;
   format _all_;  * shows you the internal value for your time column ;
run;

data want2;
   set have;
   select;
      when ("00:00:00"t <= time < "24:00:00"t) day=1;
      when ("24:00:00"t <= time < "48:00:00"t) day=2;
      when ("48:00:00"t <= time < "72:00:00"t) day=3;
      otherwise day=-1;  * representing "unknown" day ;
   end;
run;

 

See:

https://support.sas.com/documentation/cdl/en/lrcon/62955/HTML/default/viewer.htm#a000780334.htm

https://support.sas.com/documentation/cdl/en/lrcon/62955/HTML/default/viewer.htm#a002200738.htm

 

Note the 2nd link says:

 

SAS time value

      is a value representing the number of seconds since midnight of the current day. SAS time values are between 0 and 86400.

 

IMO this is incorrect given the test case above.


Please post your question as a self-contained data step in the form of "have" (source) and "want" (desired results).
I won't contribute to your post if I can't cut-and-paste your syntactically correct code into SAS.
eabc0351
Quartz | Level 8

@ScottBassyes, some version of that worked for me. Instead of days, I did hours. That provided a numeric variable (best12., not a time format) to use in the previous code. Thank you all!

data test;
   set have;
   select;
      when ("00:00:00"t <= timevar < "01:00:00"t) hours=1;
      when ("01:00:00"t <= timevar< "02:00:00"t) hours=2;
      when ("02:00:00"t <= timevar< "03:00:00"t) hours=3;
      when ("03:00:00"t <= timevar< "04:00:00"t) hours=4;
      otherwise hours=-1;  * representing "unknown" day ;
   end;
run;
ScottBass
Rhodochrosite | Level 12

@eabc0351 wrote:

@ScottBassyes, some version of that worked for me. Instead of days, I did hours. That provided a numeric variable (best12., not a time format) to use in the previous code. Thank you all!

data test;
   set have;
   select;
      when ("00:00:00"t <= timevar < "01:00:00"t) hours=1;
      when ("01:00:00"t <= timevar< "02:00:00"t) hours=2;
      when ("02:00:00"t <= timevar< "03:00:00"t) hours=3;
      when ("03:00:00"t <= timevar< "04:00:00"t) hours=4;
      otherwise hours=-1;  * representing "unknown" day ;
   end;
run;

 

I did think of another approach which, depending on your circumstances, may be a better approach.

 

The above works fine for a small number of ranges (i.e. the three you specified), but gets problematic if the number of ranges increases.

 

Another approach is to create a range format.  And, since formats can be created programatically via a cntlin dataset, you can easily create as many ranges as required.

 

Here is sample code.  Hope this helps...

 

* for debugging: create a test format with high end exclusion ;
proc format;
   value foo
      1 - < 2=1
      2 - < 3=2
   ;
run;

* for debugging: examine the format for the cntlout dataset ;
proc format cntlout=cntlout;
run;

* create a proc format cntlin dataset ;
data cntlin;
   format fmtname type start end label;  * this is just to set the PDV order and is optional ;
   length fmtname $32 type $1 eexcl $1;  * or this too could have set the PDV order ;

   fmtname='time2hours';
   type='N';
   eexcl='Y';

   start="00:00:00"t;
   do label=0 to 72;
      end=intnx('hour',start,1,'S');
      output;
      start=end;
   end;
   format start end time.;
run;

* for debugging only: show the actual (unformatted) values of start and end ;
proc print;
   format _all_;
run;

* create the format ;
proc format cntlin=cntlin;
run;

/* a quick lesson on formats/informats:
formats:    can accept either numeric or character input, always returns character output
informats:  always accepts character input, returns either numeric or character output

I used a numeric format, so it accepts numeric input (time) but returns character output (hour)
So we will need to convert the output from character to numeric using the input function
*/

data test;
   set cntlin;
   hour=input(put(start,time2hours.),best.);
run;

That provided a numeric variable (best12., not a time format)

 

The time variables are always numeric, it is only the time format that makes it appear as a "time".  There is no "best12." or "time." data type.

 


Please post your question as a self-contained data step in the form of "have" (source) and "want" (desired results).
I won't contribute to your post if I can't cut-and-paste your syntactically correct code into SAS.

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

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
  • 7 replies
  • 14650 views
  • 1 like
  • 5 in conversation