The simplest way is to get lists of the variables. Then you can use ARRAYs in the step that does the actual conversion.
You can use the FMTINFO() function to detect if the variable has a DATE or DATETIME type format attached to it. For that to work you need to bare NAME of the FORMAT, not the format specification with the width and everything. So use PROC CONTENTS to get the variable list.
proc contents data=have noprint out=contents; run;
proc sql noprint;
select case when fmtinfo(format,'cat')='date' then nliteral(name) else ' ' end
, case when fmtinfo(format,'cat')='datetime' then nliteral(name) else ' ' end
into :datevars separated by ' '
, :dtvars separated by ' '
from contents
where type=1 and format ne ' '
;
quit;
Now that you have the variable lists just make two arrays and two DO loops. Include your DO loop index variable into the array definition and the code will run fine if there are no date or no datetime variables. I assume you don't want to increment missing values.
data want;
set have;
array _dttm index &dtvars;
array _date index &datevars;
do index=2 to dim(_dttm);
if not missing(_dttm[index]) then
_dttm[index] = intnx('dtday',_dttm[index],100,'s')
;
end;
do index=2 to dim(_date);
if not missing(_date[index]) then _date[index]=_date[index]+100;
end;
drop index;
run;
Let's run proc compare and see if it worked.
The COMPARE Procedure
Comparison of WORK.HAVE with WORK.WANT
(Method=EXACT)
Value Comparison Results for Variables
__________________________________________________________
|| Base Compare
Obs || dttm dttm Diff. % Diff
________ || _________ _________ _________ _________
||
1 || 10NOV2012 18FEB2013 8640000 0.5179
2 || 06MAR2013 14JUN2013 8640000 0.5149
3 || 29MAR2022 07JUL2022 8640000 0.4399
__________________________________________________________
__________________________________________________________
|| Base Compare
Obs || date date Diff. % Diff
________ || _________ _________ _________ _________
||
1 || 12/16/20 03/26/21 100.0000 0.4491
2 || 02/26/21 06/06/21 100.0000 0.4477
3 || 03/01/21 06/09/21 100.0000 0.4476
__________________________________________________________
You could also just generate a separate IF/THEN/Assignment statement for each variable. For example by writing them to a file and then %INCLUDING the file.
filename code temp;
data _null_;
file code;
set contents;
where type=1 and format ne ' ';
length nliteral $80;
nliteral=nliteral(name);
select (fmtinfo(format,'cat'));
when ('date') put 'if not missing(' nliteral ') then ' nliteral '=' nliteral '+100;';
when ('datetime') put 'if not missing(' nliteral ') then ' nliteral
'=intnx("dtday",' nliteral ',100,"s");' ;
otherwise;
end;
run;
data want;
set have;
%include code / source2;
run;
Result
212 data want;
213 set have;
214 %include code / source2;
NOTE: %INCLUDE (level 1) file CODE is (system-specific pathname).
215 +if not missing(date ) then date =date +100;
216 +if not missing(dttm ) then dttm =intnx("dtday",dttm ,100,"s");
NOTE: %INCLUDE (level 1) ending.
217 run;
NOTE: The data set WORK.WANT has 3 observations and 4 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
... View more