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

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().

Related

How to get the current month and year in YYYYMM format in 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;

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 ;

Convert Timestamp to Numeric value in SAS

How to convert the default timestamp "0001-01-01-00.00.00.000000" in SAS, i have tried below code but it has returned null value. Can someone help on this please
data _NULL_;
x = "0001-01-01-00.00.00.000000";
rlstime = input(x,anydtdtm26.);
call symput('rlstime',rlstime);
run;
%put rlst: &rlstime;
As far as I remember, SAS cannot do that. Any date/timestamp before 1.1.1600 doesn't exist for SAS. Do you need it or can you just replace it with a null value? If you really need it you could transform it into another valid timestamp, split it into different columns (year, month, etc.) or just use it as a string. In your example you just write the timestamp into the log, meaning it's not necessary to transform it.
The earliest date that SAS will handle is 1st January, 1582. Additionally, a colon character should be used to delimit the time from the date, as well as the hours, minutes and seconds. Therefore, your code may be adjusted to the following:
data _NULL_;
x = "1582-01-01:00:00:00.000000";
rlstime = input(x,anydtdtm26.);
call symput('rlstime',rlstime);
run;
%put rlst: &rlstime;

How to subtract two dates in sas studio?

I need help with a question.
I need to subtract two dates in sas studio. I have the next:
%let date_star = %SYSFUNC( DATETIME());
%let date_end = %SYSFUNC( DATETIME());
But I dont´n now how to subtract these variables.
Thanks for your help.
Use the INTCK() function to return the number of interval boundaries of a given kind that lie between two dates, times, or datetime values. The possible values of interval are listed in Date and Time Intervals.
%MACRO want;
%let date_start = %SYSFUNC(DATETIME());
data _null_;
rc=SLEEP(10,1); /* Sleep for 10 seconds */
run;
%let date_end = %SYSFUNC(DATETIME());
%put %sysfunc(intck(second, &date_start., &date_end.));
%MEND;
%want;
Result is 10 seconds, as expected.
So you haven't really created any variables there, just macro variables. Normally you would want to use SAS code to work with data, not macro code, but you can do it in a pinch.
You also do not have two DATE values. SAS stores dates as the number of days. Instead you have two DATETIME values. The DATETIME() function returns the number of seconds since 1960. So the difference between two datetime values will be a number in seconds.
The datetime value returned by DATETIME() will include fractions of a second. To perform floating point arithmetic in macro code you need to use the %SYSEVALF() function. The %EVAL() function that is used by default to evaluate conditions, like in a %IF statement, only handles integer arithmetic.
%let elapsed_time=%sysevalf(&date_end - &date_star);
If you would like to see the value in hours, minutes and seconds then you could apply a format to it.
%put Elasped time was %sysfunc(putn(&elapsed_time,time15.3));

Automating the starting date with a macro variable in SAS

Background:
I have a code that pulls transactional data starting at the beginning of the current calendar quarter, but from an year ago.
For example, if I run the code today (August 16, 2013) it will have to pull all the data from July 1, 2012 onwards.
Problem:
I want to automate the starting date for the data pull with a macro variable.
So far, I'm stuck here:
%let ThisYear = %Sysfunc(Date(), YEAR.);
%let LastYear= %eval(&ThisYear-1); /* I get the starting year */
%let QTR_start_month= %eval(3*%Sysfunc(Date(), qtr.)-2); /* this gives me the current quarter starting month. If I run it in August, it outputs 7 for July */
%let start_date=%str(01/%Sysfunc(month(&QTR_start_month))/&lcy);
The final macro variable outputs the date which I want, but in a format which is not recognized by SAS.
I will greatly appreciate any help.
Many thanks in advance!
You can either input that date to a date format, or construct it like a SAS date literal ('01JUL2013'), DDMONYY(YY), or construct it as a date value directly.
INTNX is probably your best option here to construct it; you don't need all that work.
%let start_date = %sysfunc(intnx(Quarter,%sysfunc(date()),-4),DATE9.);
%put &start_date;
You can leave DATE9. to use it as a date literal, or remove the ,DATE9. to get the numeric value that can be used directly. You would use this as "&start_Date."d to use the date literal.
This should do the job.
data test;
format todays_date starting_qtr date9.;
todays_date=today();
/*this takes today's date and rolls back 4 qtrs and sets that date to the first day of that quarter*/
starting_qtr = intnx('qtr',todays_date,-4,'b');
/*so, running this code today, 16AUG2013 would yield starting_qtr=01JUL2012 */
call symputx('start_date', put(starting_qtr, date9.));
run;
%put &start_date.;