data _null_;
pre = put(year(intnx ('month', today(), -1)) ,8.)||'-'||put(month(intnx ('month', today(), -1)), z2.);
call symputx('prev', left(Trim(pre)));
cur = put(year(intnx ('month', today(), 0)) ,8.)||'-'||put(month(intnx ('month', today(), 0)), z2.);
call symputx('curr', left(Trim(cur)));
run;
%put &prev.;
%put &curr.;
How to convert 2020-08 to Aug-2020 and 2020-09 to Sep-2020?
You can use Picture format to get your desired outcome.
proc format ;
picture newfmt(default=6)
other='%b-%y'(datatype=date);
run;
data _null_;
call symputx('prev', put(intnx ('month', today(), -1 ),newfmt.));
call symputx('curr', put(intnx ('month', today(), 0 ),newfmt.));
run;
%put &prev.;
%put &curr.;
Output:
34 %put &prev.;
SYMBOLGEN: Macro variable PREV resolves to Aug-20
Aug-20
35 %put &curr.;
SYMBOLGEN: Macro variable CURR resolves to Sep-20
Sep-20
So if PRE is yesterday and CUR is today, and they are both obtained from the TODAY() function, there is no need for all this manipulation. And if you are creating macro variables, don't even format them (see below).
data _null_;
cur=today();
pre=cur-1;
call symputx('pre',pre);
call symputx('cur',cur);
run;
Now, we get to the critical issue of formatting macro variables. Please see Maxim 28. Macro variables should NOT be formatted. You gain nothing from this (unless you are using the formatting for labels or titles), but it takes you extra time to write the code for this. Again, you work extra hard to format macro variables, and do all these manipulations, when it is not necessary. Don't do it (except for titles or labels). Working extra to gain nothing is not the path I would choose.
Expanding on what @PaigeMiller said, once you have a proper SAS Date in your Macro variable, you just format as needed when you need it. For example, the following code will give you (displayed) the MON-CCYY format you're looking for:
data _null_;
cur=today();
pre=cur-1;
call symputx('pre',pre);
call symputx('cur',cur);
run;
%PUT %QSYSFUNC(SUBSTR(%QSYSFUNC(PUTN(&Pre, MONYY7.)), 1, 3))-%QSYSFUNC(SUBSTR(%QSYSFUNC(PUTN(&Pre, MONYY7.)), 4, 4));
Jim
I wouldn't even both trying to get the hyphen in there, it is much easier (and just as understandable for people viewing the results) to format as MONYY7. without the hyphen if you need it in titles or labels. Less work, in my mind, to get equally usable results, is always preferable.
@PaigeMiller wrote:
I wouldn't even both trying to get the hyphen in there, it is much easier (and just as understandable for people viewing the results) to format as MONYY7. without the hyphen if you need it in titles or labels. Less work, in my mind, to get equally usable results, is always preferable.
Agree.
If the hyphen were that critical I would likely make a custom Format and skip that many %sysfunc %qsysfunc calls in one statement. I'm getting to where more than 2 %sysfunc/%qsysfunc calls in a single statement tells my I may want to reconsider something.
I'm getting to where more than 2 %sysfunc/%qsysfunc calls in a single statement tells my I may want to reconsider something.
Hmmm. Good point. I have often felt that it gets a bit fiddly when you have perhaps dozens of left and right parentheses. Now, was that parenthesis for this function of for that function? Did I close that call or is this a third parameter for ... ?
Jim
I wouldn't even both trying to get the hyphen in there, it is much easier (and just as understandable for people viewing the results) to format as MONYY7. without the hyphen if you need it in titles or labels. Less work, in my mind, to get equally usable results, is always preferable.
Yeah, I think I would agree with you that 24SEP is just as understandable for most people as 24-SEP, and,
Less work, in my mind, to get equally usable results, is always preferable.
would be difficult to argue with. Programs have to be maintained, and, who knows, the next guy may not be as facile with macro functions which could lead to mis-representations of data.
Jim
The DATE11. format will generate dd-MON-yyyy. You could then just strip off the first three characters. And if you really want Sep instead of SEP you could call PROPCASE() function.
%let want=%sysfunc(propcase(%substr(%sysfunc(today(),date11.),4)));
433 %put &=want; WANT=Sep-2020
Ah. Very good. Much better than what I proposed.
Jim
You can use Picture format to get your desired outcome.
proc format ;
picture newfmt(default=6)
other='%b-%y'(datatype=date);
run;
data _null_;
call symputx('prev', put(intnx ('month', today(), -1 ),newfmt.));
call symputx('curr', put(intnx ('month', today(), 0 ),newfmt.));
run;
%put &prev.;
%put &curr.;
Output:
34 %put &prev.;
SYMBOLGEN: Macro variable PREV resolves to Aug-20
Aug-20
35 %put &curr.;
SYMBOLGEN: Macro variable CURR resolves to Sep-20
Sep-20
@SASPhile wrote:
I found the trick:
proc format ;
picture newfmt(default=10)
other='%b-%Y'(datatype=date);
run;
This gets me the desired output.
Default = 8 would likely be better to prevent leading spaces.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.