For fun I'm trying to write a macro that calculates a countdown to my approximate age of retirement.
I can't seem to get the months and days right, though.
Here's what I have so far, .
%let mybirthday = ; /* in date9 format */
DATA _NULL_;
call symput('actualend',put(intnx('years', "&mybirthday."d, 65, 'sameday'),date9.));
RUN;
DATA _NULL_;
call symput('days', INTCK('DAY',date(),"&actualend."d,'C'));
call symput('weeks', INTCK('WEEK',date(),"&actualend."d,'C'));
run;
DATA _NULL;
call symput('yrsleft', floor(&weeks./52));
run;
So far so good.
When I try to calculate months, though, using
DATA _NULL_;
call symput('mthsleft', floor((&weeks. - &years.*52)/4));
run;
I get 10, when the answer should be 9 (using Wolfram Alpha for convenience's sake).
This is my main stumbling block, can't calculate the months exactly due to the different number of days (plus leap years!).
What I'd be looking for is output like
There are V years, X months, Y weeks and Z days until $DATE.
Please help, and holy moly thank you if you made it this far :-)
CodePudding user response:
I think you need CALL IS8601_CONVERT.
dur=P2Y2M14D
data _null_;
length dur $16;
start = today();
end='18DEC2023'd;
call is8601_convert('d/d','du',start,end,dur);
put dur=$n8601e.;
run;
I found the example code here. https://www.lexjansen.com/pharmasug/2012/DS/PharmaSUG-2012-DS22-SAS.pdf
CodePudding user response:
You can, and should, do everything with intck
/ intnx
to avoid issues like this. Just calculate each years/months value separately, and then increment the base date by that much. So calculate year difference, then however many years it was, make a new variable with date() yrsleft as a value.
So if it's 10/4/2021, and you're retiring on 7/15/2049, then yrsleft is 27 - and the new variable stores 10/4/2048. Then do the same for the months - 9 months between 10/4/2048 and 7/15/2049, and that takes you to 7/4/2049, so store that in another variable. Then just subtract to get the days.
DATA _NULL_;
*calculate YRSLEFT and then store the "ending year" point in a variable;
yrsleft = intck('Year',date(),"&actualend."d,'c');
year = intnx('year',date(),yrsleft,'s');
put year= date9.;
*calculate MTHSLEFT and then store the "ending month" point in a variable;
mthsleft=intck('Month',year,"&actualend."d,'c');
month = intnx('month',year, mthsleft,'s');
*store them in macro variables;
call symputx('yrsleft', yrsleft);
call symputx('mthsleft',mthsleft);
*calculate days left directly;
call symputx('daysleft',"&actualend."d - month);
run;
%put &=yrsleft &=mthsleft &=daysleft;