How to get the current month and year in YYYYMM format in SAS? - sas

I want to use Call Symput and define a variable called "Current_Month" which will give me the year and month in YYYYMM format. For instance, for the current month Feb'2023, the output should come as 202302. Any help would be appreciated!

Using straight macro logic:
today() function to generate today's date
sysfunc() to call the today() function within the macro. Note the second parameter to sysfunc() can be a format to format the output.
%let currentMonth = %sysfunc(today(), yymmn6.);
%put &currentMonth.;
log:
68
69 %let currentMonth = %sysfunc(today(), yymmn6.);
70
71 %put &currentMonth.;
202302

You can use call symputx() in a data step to generate a macro variable. (you would only want to use the older call symput() routine if you need the macro variable to contain trailing or leading spaces).
You can use the YYMMN6. format to display a date value as a digit string where the digits represent the four digit year and two digit month of the date.
data _null_;
call symputx('current_month',put(today(),yymmn6.));
run;

Related

SAS macro to get the last date of the current month

I would like to use a macro in SAS to calculate the last day of the current month when executed.
As i'm quite new to the SAS macro's i've tried to create on based on the information i've found on the internet.
%let last_day = %sysfunc(putn(%sysfunc(intnx(month,%sysfunc(today()),e), date9.));
However it does not seem to work when i execute it.
You left out the number of intervals in the INTNX() function call.
To create a macro variable with the string that looks like the last day of the current month in the style produced by the DATE9. format just use:
%let last_day = %sysfunc(intnx(month,%sysfunc(today()),0,e), date9.);
You could then use that macro variable to generate strings. Such as in a TITLE statement.
TITLE "End of the month is &last_day";
If you want to use it as an actual date you will need to convert it to a date literal by adding quotes and the letter d.
...
where date <= "&last_day"d ;
And if so it is probably simpler to not use the DATE9. format at all and just store the raw number of days since 1960 in the macro variable.
%let last_day = %sysfunc(intnx(month,%sysfunc(today()),0,e));
...
where date <= &last_day ;

write conditional in SAS with DATA _NULL_

I am writing a conditional in SAS starts with DATA NULL
%LET today = today();
DATA _NULL_;
if day(today) ge 1 and day(today) le 15 then do;
date1=put(intnx('month',today,-1,'E'), date11.);
date2=put(intnx('month',today,-1,'L'), date11.);
end;
if day(today) > 15 then do;
date1=put(intnx('month',today,0,'B'), date11.);
date2=put(intnx('month',today,0,'L'), date11.);
end;
call symput('report_date',date1);
call symput('report_date2',date2);
RUN;
but with above, I am not getting any values for my report_dates.
the condition is:
date 1 = If the current date is greater than or equal to 1 and less than 16, set the date1 to the 16th of the previous month, otherwise set it to the 1st of the current month
date2 = If the current date is 16 and above, set the date2 to the 15th of the current month, otherwise set date2 to the last day of the previous month
The IF/THEN logic does not account for the missing value you passing to the DAY() function calls.
The variable TODAY is never created in the data step. So just remove the %LET statement and add an actual assignment statement instead.
DATA _NULL_;
today=today();
if day(today) ge 1 and day(today) le 15 then do;
...
Just because you used the same name for the macro variable in the %LET statement as you used for the variable in the data step does not imply that the two have anything at all to do with each other.
If you wanted to use the macro variable to generate the code for the data step you would need to replace the TODAY with &TODAY.
if day(&today) ge 1 and day(&today) le 15 then do;
So for the value you set to the macro variable TODAY it would mean that the SAS code you are trying to run is:
if day(today()) ge 1 and day(today()) le 15 then do;
Note that is actually not a good way to handle this problem because it is calling the TODAY() function multiple times. That could cause strange results if the data step started right before midnight. So the IF condition might be run on the 31st but when you get to the ELSE condition the clock has ticked over to the first of the next month.

How to create a datetime macro variable in SAS

%let mydate = "01JUN2021 00:00:00.000"dt;
This does not work. How do I create a datetime macro variable without using proc sql or data step?
The pure macro solution is:
%let mydate = %sysfunc(dhms(%sysfunc(mdy(6,1,2021)), 0, 0, 0));
%put &=mydate; * PRINTS THE UNFORMATTED VALUE STORED;
%put %sysfunc(sum(&mydate), datetime22.); * PRINTS THE DATETIME VALUE FORMATTED;
Output:
MYDATE=1938124800
01JUN2021:00:00:00
You can of course perform the dhms() and mdy() functions on separate lines if that is clearer for you.
Compare this to what your orginal code is doing:
%let mydate="01jan2021:00:00:00"dt;
%put &=mydate;
Prints:
MYDATE="01jan2021:00:00:00"dt
Notice how in your approach the string "01jan2021:00:00:00"dt has been saved into the macro variable, rather than the actual numeric date value 1938124800? Sometimes when you use your approach SAS gets confused when you try to use the value and it is unable to translate the literal to a numeric date value.
try %let mydate = '1Jan2021:0:0:1'dt
Note that it uses single quotes & theres no space between date and time
Your posted macro variable works fine in SAS code.
82 %let mydate = "01JUN2021 00:00:00.000"dt;
83
84 data test;
85 now = datetime();
86 then = &mydate;
87 diff = intck('dtday',then ,now);
88 format now then datetime20. ;
89 put (_all_) (=);
90 run;
now=16JUN2021:08:18:33 then=01JUN2021:00:00:00 diff=15
NOTE: The data set WORK.TEST has 1 observations and 3 variables.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
If you need to use the value in pass through SQL code then you will need to set the macro variable to text that the remote database's implementation of SQL will recognize as a datetime value.
So perhaps
%let myts = timestamp '2021-06-01 00:00:00.000';

Input date format YYYYMMDD

I need to input dates in YYYYMMDD format and create macro variables from these dates to use in a WHERE clause. The FINAL dataset should select one record from Sales but 0 observations are returned.
data work.FiscalYear2019;
input #1 fiscalYear $4. #5 StartDate mmddyy8.;
retain diff;
if fiscalYear = '2019' then do;
tday = today();
diff = tday - StartDate;
call symputx('FYTD_days',diff);
call symputx('CY_StartDate', StartDate);
call symputx('CY_EndDate', put(today(),mmddyy8.));
end;
else if fiscalYear = '2018' then do;
PY_EndDate = StartDate + diff;
call symput('PY_EndDate', put(PY_EndDate,mmddyy8.));
call symput('PY_StartDate', put(StartDate,mmddyy8.));
end;
datalines;
201912312018
201801012018
;
data work.Sales;
input #1 fiscalYear $4. #5 orderDate mmddyy8.;
format orderDate mmddyy6.;
datalines;
201902042019
201801012018
;
data final (WHERE=(orderDate >= &PY_StartDate AND
orderDate <= &PY_EndDate));
set Sales;
run;
I expect the FINAL dataset to contain one record from the Sales dataset but FINAL has 0 observations.
To use your macro variables as date values you need to either generate the macro variables as the raw number of days values, like you did with CY_StartDate, or generate them using the DATE format and enclose them in quotes and append the letter D to make a date literal.
Like this:
call symputX('PY_StartDate', put(StartDate,date9.));
call symputX('PY_EndDate', PY_EndDate);
...
data final
set Sales;
WHERE orderDate >= "&PY_StartDate"d
AND orderDate <= &PY_EndDate
;
run;
Also your subject line mentions YYYYMMDD informat and it does not appear in your code. Are you interpreting your source data properly? Does 201801012018 represent an 8 digit date in YMD order plus a four digit year? Or a four digit year plus an 8 digit date in MDY order?
You are just not referring to your macro variables in the last data step with the proper syntax. Those &PY_StartDate and &PY_EndDate variables are just strings after macro code is compiled, and you need to refer to them as date constants. So this should fix the issue:
data final (WHERE=(orderDate >= "&PY_StartDate"d AND
orderDate <= "&PY_EndDate"d));
set Sales;
run;
In the future, I recommend including options mprint; at the start of your code. This option displays the text generated by macro execution in your log, which can help greatly with debugging macros.

SAS - adding date format to the macro variable giving strange results

My question is as follows -
I have a code that adds one month to the macro variable and the code works fine:
%let month=1;
%let act_dt = %sysfunc(MDY(&month,1,2016));
%let x_akt=%sysfunc(intnx(MONTH,&act_dt,1),yymmdd10.);
%put current month: &act_dt;
%put plus one month: &x_akt;
giving me the output:
current month: 20454
plus one month: 2016-02-01
But if I add a type of format to the first macro variable, then the function intnx does not work properly.
%let month=1;
%let act_dt = %sysfunc(MDY(&month,1,2016),yymmdd10.);
%let x_akt=%sysfunc(intnx(MONTH,&act_dt,1),yymmdd10.);
%put current month: &act_dt;
%put plus one month: &x_akt;
with the outcome:
current month: 2016-01-01
27 %put plus one month: &x_akt;
plus one month: 1965-08-01
Thank you for any advice, why is it like that and if there is a way how to present both macro variables in the same format.
You can see most of the reason where your first log gives 'current month' as 20454. That's clearly not a human-readable date. In fact, it's SAS's internal representation of the date 1st Jan 2016, represented as the number of days since 1st January 1960.
Your first example works because it passes that numeric value to the INTNX() function, which is what that function needs and expects. Your second example passes the character value '2016-01-01' to the function, which SAS tries to handle by partially converting it to the numeric value 2016, which (taken as a number of days since 1st Jan 1960) is 9th July 1965. The INTNX() function then moves that forward by one month as before.
All SAS date/time function expect to receive numeric input. There is no separate date/time data type in SAS, just numerics with particular date/time formats applied to them. To work in macro variables, your code must either store and manipulate the date values as numbers and then only convert them with a PUT() function for display, or else store them as formatted dates but always convert them back to numeric with a %SYSFUNC(INPUT()) when passing the value to a date/time function.
It's often clearer to do this kind of manipulation in a short DATA _NULL_ step than to have lots of macro code full of %SYSFUNCS().