Get out of the habit of working with dates as text strings. In SAS, dates should always be numbers, the integer number of days after 01JAN1960. SAS does not recognize 20180620 as a date, even if humans do recognize it as a date. It needs to be converted to an actual numeric SAS date value, and then and only then will the MONTH() function work. SAS has done all the necessary creating functions formats and informats to work with dates, so you don't have to struggle with these things.
Furthermore, there seems to be no need for a macro here, and no need for macro variables or SYSFUNC either. You can use a DO loop in a SAS data step. Do not make programming more complicated than it has to be.
data pop;
/*set pop;*/ /* this is commented out because I don't have your data set */
predate=20180620; /* This is not a SAS date, you have to convert it to a SAS date */
predate1=input(put(predate,8.),yymmdd8.); /* Convert it to a SAS date, which is 21355 to SAS or to us humans it is 20JUN2018 */
mo_before=month(predate1);
format predate1 date9.;
run;
The dates were never text strings, they are dates in YYMMDDN. format. Converting to YYMMDD8. format did not work. And as far as I can tell, it does need to be a macro. I removed a block of code from this post to remove distractions from my issue at hand, but I need it to be a macro so that I can dynamically reference variables that end in the suffix of &mo (01 to 12).
The issue at hand is that I cannot set a macro variable to the numeric month from a sas date
@reubendon wrote:
The dates were never text strings, they are dates in YYMMDDN. format.
The issue at hand is that I cannot set a macro variable to the numeric month from a sas date
Okay, please clarify. Are the date value stored in numeric variables according to PROC CONTENTS (or similar), and the format is YYMMDDN. ? Or are they really the value 20180620? Show us the PROC CONTENTS output for this variable.
With regards to your macro statements, please explain further ... and in detail ... the values 01 to 12 can all be handled in a DATA step loop with an ARRAY. In addition, %SYSFUNC cannot access values in a SAS data set variable, like the variable you have named PRE_DATE01 PRE_DATE02 ...
Proc contents output:
135136137138139140141142143144145146
pre_date01 | Num | 8 | YYMMDD8. | |
pre_date02 | Num | 8 | YYMMDD8. | |
pre_date03 | Num | 8 | YYMMDD8. | |
pre_date04 | Num | 8 | YYMMDD8. | |
pre_date05 | Num | 8 | YYMMDD8. | |
pre_date06 | Num | 8 | YYMMDD8. | |
pre_date07 | Num | 8 | YYMMDD8. | |
pre_date08 | Num | 8 | YYMMDD8. | |
pre_date09 | Num | 8 | YYMMDD8. | |
pre_date10 | Num | 8 | YYMMDD8. | |
pre_date11 | Num | 8 | YYMMDD8. | |
pre_date12 | Num | 8 | YYMMDD8. |
entire code:
%macro test; data pop; set pop; %do i = 01 %to 12; /* &mo_before is the amount of months before DT_INDEX */ %let mo_before = %sysfunc(putn(&i, z2.)); /* &mo is the actual month associated with the date 1,2,3,...12 months before DT_INDEX */ %let mo = %sysfunc(month(pre_date&mo_before)); /* If the row's year matches the date 1,2,...months before DT_INDEX */ if year(pre_date&mo_before) = REF_YR then do; /* If the CST_SHR_GRP_CD_ variable corresponding to date&mo_before's month is between "01" and "08" */ if "01" <= CST_SHR_GRP_CD_&mo <= "08" /* Then LIS_PRE_ corresponding to 1,2,3,...12 months before is 1 */ then LIS_PRE_&mo_before = 1; else LIS_PRE_&mo = 0; end; %end; run; %mend; %test;
data pop1; /* Very important, do not overwrite existing data sets */
set pop;
array p pre_date01-pre_date12;
do i = 1 to 12;
/* &mo_before is the amount of months before DT_INDEX */
/* mo_before = i; */ /* Not needed, I think */
mo = month(p(i));
end;
run;
I think there's still something I don't understand about what you are doing, but the above should get you going in the right direction. Also the variable MO isn't really stored in each iteration, I suspect you want that but your actual code doesn't store it either.
The text "predate01" is clearly not a number, and also not a macro variable reference which could resolve to a number.
You cannot access a data step variable in macro language like this; the macro preprocessor works before code is even sent to the data step compiler.
To loop through a set of data step variables, define an array for them and use a data step DO loop.
Sure but even this still gives me an issue:
%let
m = month(pre_date&mo_before); /* This line works fine*/
%let mo_before = %sysfunc(putn(m, z2.)); /*This line does does*/
m is not a number.
See my previous post why this CANNOT work.
To dynamically address variables in a data step, use arrays.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
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.
Ready to level-up your skills? Choose your own adventure.