Hello,
I am trying to set a &start_date and &end_date based on todays date. If the day of the month is after the 16th id like the end_date to be the 15th of current month. If the day of the month is before the 16th, id like the end_date to be the end of the prior month. Hope that makes sense.
You are asking how to compute the end of either the prior semimonth or month depending on day in month.
%macro end_date_test; %do today = %sysevalf("01JUL2020"D) %to %sysevalf("31JUL2020"D); %if %sysfunc(day(&today)) >= 16 %then %do; %let end_date = %sysfunc(intnx(semimonth2.2, &today, -1, E)); %end; %else %do; %let end_date = %sysfunc(intnx(month, &today, -1, E)); %end; %put today=%sysfunc(putn(&today,date9.)) end_date=%sysfunc(putn(&end_date,date9.)); %end; %mend; %end_date_test;
The log should convince you the end_date computation meets your business rules
today=01JUL2020 end_date=30JUN2020 today=02JUL2020 end_date=30JUN2020 today=03JUL2020 end_date=30JUN2020 today=04JUL2020 end_date=30JUN2020 today=05JUL2020 end_date=30JUN2020 today=06JUL2020 end_date=30JUN2020 today=07JUL2020 end_date=30JUN2020 today=08JUL2020 end_date=30JUN2020 today=09JUL2020 end_date=30JUN2020 today=10JUL2020 end_date=30JUN2020 today=11JUL2020 end_date=30JUN2020 today=12JUL2020 end_date=30JUN2020 today=13JUL2020 end_date=30JUN2020 today=14JUL2020 end_date=30JUN2020 today=15JUL2020 end_date=30JUN2020 today=16JUL2020 end_date=15JUL2020 today=17JUL2020 end_date=15JUL2020 today=18JUL2020 end_date=15JUL2020 today=19JUL2020 end_date=15JUL2020 today=20JUL2020 end_date=15JUL2020 today=21JUL2020 end_date=15JUL2020 today=22JUL2020 end_date=15JUL2020 today=23JUL2020 end_date=15JUL2020 today=24JUL2020 end_date=15JUL2020 today=25JUL2020 end_date=15JUL2020 today=26JUL2020 end_date=15JUL2020 today=27JUL2020 end_date=15JUL2020 today=28JUL2020 end_date=15JUL2020 today=29JUL2020 end_date=15JUL2020 today=30JUL2020 end_date=15JUL2020 today=31JUL2020 end_date=15JUL2020
Inside a macro
%let date=%sysfunc(today());
%if %sysfunc(day(&date))<16 %then %let enddate=%sysfunc(intnx(month,&date,-1,e));
%else %let enddate=%eval(%sysfunc(intnx(month,&date,0,b))+14);
data _null_;
if day(today()) < 16 call symputx('end_date',intnx('month',today(),-1,'END'));
else call symputx('end_date',intnx('month',today(),0,'END'));
run;
What if day of the month EQUALS 16 ?
@RichardDeVen wrote:
What if day of the month EQUALS 16 ?
An excellent question. But hopefully the OP can make the modifications to the above code to handle this issue.
You are asking how to compute the end of either the prior semimonth or month depending on day in month.
%macro end_date_test; %do today = %sysevalf("01JUL2020"D) %to %sysevalf("31JUL2020"D); %if %sysfunc(day(&today)) >= 16 %then %do; %let end_date = %sysfunc(intnx(semimonth2.2, &today, -1, E)); %end; %else %do; %let end_date = %sysfunc(intnx(month, &today, -1, E)); %end; %put today=%sysfunc(putn(&today,date9.)) end_date=%sysfunc(putn(&end_date,date9.)); %end; %mend; %end_date_test;
The log should convince you the end_date computation meets your business rules
today=01JUL2020 end_date=30JUN2020 today=02JUL2020 end_date=30JUN2020 today=03JUL2020 end_date=30JUN2020 today=04JUL2020 end_date=30JUN2020 today=05JUL2020 end_date=30JUN2020 today=06JUL2020 end_date=30JUN2020 today=07JUL2020 end_date=30JUN2020 today=08JUL2020 end_date=30JUN2020 today=09JUL2020 end_date=30JUN2020 today=10JUL2020 end_date=30JUN2020 today=11JUL2020 end_date=30JUN2020 today=12JUL2020 end_date=30JUN2020 today=13JUL2020 end_date=30JUN2020 today=14JUL2020 end_date=30JUN2020 today=15JUL2020 end_date=30JUN2020 today=16JUL2020 end_date=15JUL2020 today=17JUL2020 end_date=15JUL2020 today=18JUL2020 end_date=15JUL2020 today=19JUL2020 end_date=15JUL2020 today=20JUL2020 end_date=15JUL2020 today=21JUL2020 end_date=15JUL2020 today=22JUL2020 end_date=15JUL2020 today=23JUL2020 end_date=15JUL2020 today=24JUL2020 end_date=15JUL2020 today=25JUL2020 end_date=15JUL2020 today=26JUL2020 end_date=15JUL2020 today=27JUL2020 end_date=15JUL2020 today=28JUL2020 end_date=15JUL2020 today=29JUL2020 end_date=15JUL2020 today=30JUL2020 end_date=15JUL2020 today=31JUL2020 end_date=15JUL2020
Interesting, I knew SEMIMONTH existed but have never used it. Thanks!
Apparently, in February, the SEMIMONTH is always the 15th, leap year or not.
Open code %if %then %do
blocks is a new feature in newer SAS versions, so extricate the assignment logic from the testing macro and use it open code. Directly assign the today
macro variable the result of the TODAY()
function. I use today
macro variable because the concept/value of today is used in three places in order to properly assign the end_date
its needed value.
%let today = %sysfunc(TODAY()); %if %sysfunc(day(&today)) >= 16 %then %do; %let end_date = %sysfunc(intnx(semimonth2.2, &today, -1, E)); %end; %else %do; %let end_date = %sysfunc(intnx(month, &today, -1, E)); %end;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.