03-08-2017 06:52 AM
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 Last year
Today 3Mths ago
Today 6Mths ago
Today 9Mths ago
First Day of Prev Month
Last Day of Prev Month
03-08-2017 06:59 AM
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.
03-08-2017 07:17 AM
I'd want a macro because I reference these dates a lot and would make my code more aesthetically pleasing.
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
03-08-2017 07:36 AM
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.
03-08-2017 10:31 AM
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).
03-08-2017 07:48 AM
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 @KurtBremser 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:
Compare this to simple base SAS:
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.
03-08-2017 07:55 AM - edited 03-08-2017 08:03 AM
So can I not create %let satatements for each date I will want to use?
Of course you can. But look at this:
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.
03-08-2017 08:12 AM
DO YOU MEAN...
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.
03-08-2017 07:50 AM
@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.
03-08-2017 06:59 AM
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')
03-08-2017 07:03 AM - edited 03-08-2017 07:13 AM
/*=== 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 ===*/
...... /* choose your macro variable names and assign the dates calculated */