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

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

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