BookmarkSubscribeRSS Feed
Hoz
Calcite | Level 5 Hoz
Calcite | Level 5

I would like to check whether two period of date was overlapped or not.

%macro period(x,y);
  %if &x < &y %then %let ret = %eval(&y-&x);
  %else %let ret = 0;
  &ret
%mend period;


data aa;

  format c2 c1 yymmdd10.;
  c2 = input( "2009/09/20", yymmdd10.);
  c1 = input( "2009/09/28", yymmdd10.);
  r1 = %period(c2,c1);

run;

Above script had no error but r1 = 0. (i.e. 2009/09/20 > 2009/09/28)

Why the result is  =0 , not =8 ??

Thank you,

7 REPLIES 7
Haikuo
Onyx | Level 15

data aa;

  format c2 c1 yymmdd10.;

  c2 = input( "2009/09/20", yymmdd10.);

  c1 = input( "2009/09/28", yymmdd10.);

  call symput ('c2',c2);

  call symput ('c1',c1);

  r1 = %period(&c2,&c1);

  put r1;

run;

Notice the difference? %period will not take expressions, rather, just strings.

Regards,

Haikuo

Hoz
Calcite | Level 5 Hoz
Calcite | Level 5

Dear Hai.kuo. Thank you for your quick response.

But the code does not work...

Best Regards,

MichelleHomes
Meteorite | Level 14

Hi Hoz,

The reason why the code doesn't return 8 as you expect is due to tokenization with the SAS macro facility happening before the data step is being compiled and executed. The %period macro is being called but &c2 and &c1 in Haikuo's code doesn't exist yet due to the macros being in the symbol table only at data step execution.

You can modify your code to the following which works but I assume you want to apply this method to an entire dataset rather than just 1 row...

%macro period(x,y);

  %if &x < &y %then %let ret = %eval(&y-&x);

  %else %let ret = 0;

  &ret

%mend period;

data aa;

  format c2 c1 yymmdd10.;

  c2 = input( "2009/09/20", yymmdd10.);

  c1 = input( "2009/09/28", yymmdd10.);

  call symputx('c2',c2);

  call symputx('c1',c1);

run;

data bb;

    set aa;

    r1 = %period(&c2,&c1);

run;

Clearly if you have more than 1 observation then this method will not suit. As I am not sure what your overall requirement is then I am not sure how best to advise but I hope the above helps and shows you that you can get the value 8 as you expect.

Cheers,

Michelle

//Contact me to learn how Metacoda software can help keep your SAS platform secure - https://www.metacoda.com
Hoz
Calcite | Level 5 Hoz
Calcite | Level 5

Dear Michelle,

Thank you for detailed description.
I have red Phuse's documents, however I don't understand the mechanism between macro phase and data step especially...

My final purpose was to check whether two period of date  was overlapped or not.
The script that I thought was following:

%macro period(x1,y1,x2,y2);
   %if &x1 le &y2 and &x2 le &y1 %then %do;
      %if &x1 le &x2 %then %let start = &x2;
         %else %let st = &x1;
      %if &y1 le &y2 %then %let end = &y1;
         %else %let end = &y2;
      %let return = &&ed - &&st + 1;
   %end;
   &return
%mend period;


data aa;
  a1 = "2009/08/29";
  a2 = "2009/09/29";
  b1 = "2009/09/28";
  b2 = "2009/10/29";

  format c1 c2 c3 c4 yymmdd10.;
  c1 = input( a1, yymmdd10.);
  c2 = input( a2, yymmdd10.);
  c3 = input( b1, yymmdd10.);
  c4 = input( b2, yymmdd10.);
 
  x1 = %dupperiod(c1,c2,c3,c4);
run;

But it didn't work...so I thought to create more simple script, that was good approach at first.

My desire of macro was:

  array a_start() a_start1-a_start10;
  array a_end() b_start() b_end()
  do i=1 to dim();
     period&i = %period(a_starat, a_end, b_start, b_end);
  end;

Best Regard,

MichelleHomes
Meteorite | Level 14

Hi Hoz,

I highly recommend spending some time to read the Macro Language Reference guide starting at http://support.sas.com/documentation/cdl/en/mcrolref/62978/HTML/default/viewer.htm#p1ccprwibo8gvqn1q... or to attend a SAS Macro training course.

With regards to your code/task to create 10 start & end dates and then call your %period for each of them. I would probably use PROC SQL to create all the macro variables instead of a data step and then use a macro loop to call %period on the macro variables.

Example code on how to create macro variables using SQL can be found here: http://support.sas.com/documentation/cdl/en/mcrolref/62978/HTML/default/viewer.htm#n1y2jszlvs4hugn14...

Hope this helps.

Cheers,

Michelle

//Contact me to learn how Metacoda software can help keep your SAS platform secure - https://www.metacoda.com
Patrick
Opal | Level 21

I believe the general rule for all coding must be to keep things as simple as possible.

In a "SAS context" this means to only use macro code if it can't be done in normal Base SAS language - which in your case is clearly not the case.

/* simple SAS datastep coding */
data aa;
  format c2 c1 yymmdd10.;
  c2 = input( "2009/09/20", yymmdd10.);
  c1 = input( "2009/09/28", yymmdd10.);

  if c2<c1 then r1=c1-c2;
  else r1=0;
  put r1=;
run;

If it must be a macro then below code would work:


/* using a macro */
%macro period(arg1,arg2,ret);
  if &arg2<&arg1 then &ret=&arg1-&arg2;
  else &ret=0;
%mend;

data aa;
  format c2 c1 yymmdd10.;
  c2 = input( "2009/09/20", yymmdd10.);
  c1 = input( "2009/09/28", yymmdd10.);

  %period(c1,c2,r1)
  put r1=;
run;

It seems what you're actually trying to do is to create your own function. This is possible since SAS9.2 using PROC FCMP.

This can be very powerful - but also here I would use this option with great care and only if there is good reason as it complicates things (eg. if you start to build up your own function library and then use it everywhere so that even experienced SAS coders first need a year of induction to understand all your new functions in order to maintain the code you implemented).


/* creating and using a function */
proc fcmp outlib=work.funcs.myfuncs;;
  function period(arg1,arg2); 
    if arg2<arg1 then ret=arg1-arg2;
    else ret=0;
    return (ret);
  endsub;
run;

options cmplib=work.funcs;

data aa;
  format c2 c1 yymmdd10.;
  c2 = input( "2009/09/20", yymmdd10.);
  c1 = input( "2009/09/28", yymmdd10.);

  r2=period(c1,c2);
  put r2=;

run;

Hoz
Calcite | Level 5 Hoz
Calcite | Level 5

Dear Michelle and Patrick,

I appreciate your useful advice.

Based on your advice, it'll be done in Base SAS.


My environment is in SAS 9.1, no use PROC FCMP.
If it'll have updated 9.2, i want to understand feature of PROC FCMP.

And i will learn the macro with url which of michelle advices.


Best Regard,

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!

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
  • 1591 views
  • 0 likes
  • 4 in conversation