From now on, ALWAYS (that's 100% of the time, no exceptions) when you have to do arithmetic or logical operations on dates (like finding previous date, or comparing one date to another), you need to use valid SAS numeric dates, which are the number of days since 01JAN1960. Do not work with dates as strings like 08DEC2023 that you then have to pull apart and perform your own arithmetic on, and combine in some meaningful way.
SAS has already done the hard work by providing functions, formats and informats that make handling dates as valid numeric SAS dates very very easy, so you don't have to figure out how to handle them yourself. The INTNX function, with the WEEKDAY time interval and -1 as the increment, finds the previous weekday, it knows that the previous weekday from a Monday is the Friday before and does the arithmetic for you.
This code illustrates that
%let current_date = %sysfunc(today()); /* Today is 11DEC2023, the integer value for this date is 23355 */
%let holiday_list = 08DEC2023 25DEC2023;
/* Function to check if a date is in the holiday list */
%macro is_holiday(date);
%let holiday = 0;
%do i = 1 %to %sysfunc(countw(&holiday_list));
%let this_holiday=%scan(&holiday_list,&i,%str( )); /* Find the i-th holiday from the list in &holiday_list */
%let this_holiday=%sysfunc(inputn(&this_holiday,date9.)); /* Convert to actual numeric SAS date value, which for 08DEC2023 is 22352 */
%let prev_working_date=%sysfunc(intnx(weekday,&date,-1)); /* Use INTNX with the WEEKDAY interval to find the previous weekday */
/* &DATE is 11DEC2023, which is 23355; &prev_working_date is the previous Weekday which is Friday which is 08DEC2023 which is 23352 */
%if &prev_working_date = &this_holiday %then %let holiday = 1; /* Is holiday the previous weekday? */
%let prev_working_date=%eval(&prev_working_date-&holiday);
%let human_readable_date=%sysfunc(putn(&prev_working_date,date9.));
%put &=i &=date &=this_holiday &=prev_working_date &=holiday &=human_readable_date;
%if &holiday=1 %then %goto finish;
%end;
%finish:
%mend;
%is_holiday(¤t_date)
Only if you need dates that are readable by humans would you format the values. So this line in the code produces a human readable date, for example, 07DEC2023
%let human_readable_date=%sysfunc(putn(&prev_working_date,date9.));
... View more