Hello,
I'm looking to create macros in SAS that will allow me to quick reference dates in my code.
I would like to have the following...
Today
Today Last year
Today 3Mths ago
Today 6Mths ago
Today 9Mths ago
First Day of Prev Month
Last Day of Prev Month
Thanks,
Cam
Why would you need macro when there is perfectly good functions for this:
Today = today()
Today Last year = intnx('year',today(),-1)
Today 3Mths ago = intnx('month',today(),-3)
Today 6Mths ago ... same
Today 9Mths ago ... same
First Day of Prev Month = intnx('day',intnx(month,today(),-1),1,'b')
Last Day of Prev Month = intnx('day',intnx(month,today(),-1),1,'e')
There is never a need to use macro.
Hi,
I'd want a macro because I reference these dates a lot and would make my code more aesthetically pleasing.
Thanks,
Cam
@CamRutherford wrote:
Hi,
I'd want a macro because I reference these dates a lot and would make my code more aesthetically pleasing.
Thanks,
Cam
If you include my code in your autoexec, no macro is needed. The macro variables will be created in the global symbol table.
"autoexec" could be:
- the autoexec_usermods.sas file in your configuration
- any autoexec.sas file used by a sas start script/command (ie sasbatch)
- in the "custom code" to be sent when a server connection is opened in Enterprise Guide
- in a "autoexec" process flow in your EG projects
call symput creates macro variables. Use the string supplied to the call routine as the first parameter as a macro variable reference, eg &today for todays's date. Note that it is the raw SAS date value (number of days from 01jan1960), hard to read for humans, but very easy to use in comparisons etc.
@CamRutherford wrote:
How would I reference each date though?
I do something along these lines with a call in my autoexec to create a macro variable with a specific format that I use in title statements. The varible created is named prepdate. When I want to use it:
title2 "Prepared on: &prepdate";
You don't mention HOW you intend to use any of these variables. Do you want TEXT that is human readable or the Values that are used in comparisons (or possibly both which would work best with 2 variables, one for text and one for value).
You may believe that macro is more aesthetically pleasing, I would just call it obfuscation. SAS Programmers should all know or be able to look up the methodology of the various functions within Base SAS - this being the programming language. They would not however know all about your particular mass of %&'s. As @Kurt_Bremser has stated you can use the code in a datastep to generate the required macro parameters, but do bear in mind these will be character, and you will always have to convert each time you want to use them further. For instance, if you wanted yesterday, you would need:
intnx('day',input("&my_today_value",datetime.),-1);
Compare this to simple base SAS:
intnx('day',today(),-1);
Now add up every time you need to do that and you will see the number of processing/characters needed would in many cases exceed the benefit of storing some add-hoc dates.
So can I not create %let satatements for each date I will want to use?
@CamRutherford wrote:
So can I not create %let satatements for each date I will want to use?
Of course you can. But look at this:
%let lst_year=%sysfunc(intnx(year,%sysfunc(today()),-1,same),best.);
vs
data _null_;
date = intnx('year',today(),-1,'same');
call symput('lst_year',put(date,best.));
run;
and tell me which is easier to decipher.
PS I forgot to mention that both examples create identical macro variables.
@CamRutherford wrote:
DO YOU MEAN...
%let lst_year=%sysfunc(intnx(month,%sysfunc(today()),-1,same)),best.));
Yep. Changed my post. My maxim is that if there is more than one %sysfunc in a statement, I switch to a data step to get rid of the %sysfuncs.
This also makes your code easier to maintain, as more complex logic doesn't become as unwieldy in a data step as it does in a macro %let.
@RW9 keep in mind that I deliberately use the best. format for my "date" macro variables, so the raw values can be directly used in comparisons and calculations.
data _null_;
date = today();
call symput('today',put(date,best.));
date = intnx('year',today(),-1,'same');
call symput('today_lst',put(date,best.));
date = intnx('month',today(),-3,'same');
call symput('today_3m',put(date,best.));
date = intnx('month',today(),-6,'same');
call symput('today_6m',put(date,best.));
date = intnx('month',today(),-9,'same');
call symput('today_9m',put(date,best.));
date = intnx('month',today(),-1,'begin');
call symput('lst_month_1st',put(date,best.));
date = intnx('month',today(),-1,'end');
call symput('lst_month_lst',put(date,best.));
run;
Put that into an include file or into a macro of your choice.
(In case you put it into a macro, use call symputx with 'g')
data _NULL_;
/*=== calculate dates ===*/
dt = today();
dt_3y = intnx('year',dt,-3,'same');
dt_3m = intnx('month',dt,-3,'same');
dt_6m = intnx('month',dt,-6,'same');
dt_9m = intnx('month',dt,-9,'same');
dt_fpm = intnx('month',dt,-1,'beginning');
dt_lpm = intnx('month',dt,-1,'end'); /* or = toady() - day(today()); */
/*=== assign dates to macro variables ===*/
call symput('toady',left(dt));
call symput('dt_3y',left(dt_3y));
...... /* choose your macro variable names and assign the dates calculated */
run;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.