SAS: macro error with date - date

I am trying to create last date of the month using sas macro. I set year-month yyyymm and would like to get last date of the month
%LET YYYYMM = 201501;
%LET SASDATE = %EVAL(%SYSFUNC(INTNX('MONTH',%SYSFUNC(MDY(%SYSFUNC(MOD(&YYYYMM,100)),1,%SYSFUNC(ROUND(%EVAL(&YYYYMM/100))))),1))-1);
%PUT &SASDATE;
I am getting the following error in the log file. which I don't understand
24 %LET YYYYMM = 201501;
25 %LET SASDATE =
25 ! %EVAL(%SYSFUNC(INTNX('MONTH',%SYSFUNC(MDY(%SYSFUNC(MOD(&YYYYMM,100)),1,%SYSFUNC(ROUND(%EVAL(&YYYYMM/100))))),1))-1);
WARNING: Argument 1 to function INTNX referenced by the %SYSFUNC or %QSYSFUNC macro function is out of range.
NOTE: Mathematical operations could not be performed during %SYSFUNC function execution. The result of the operations have been set
to a missing value.
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was:
.-1
Can you please help? Thanks.

You can (and should!) use date formats and informats to deal with this sort of thing rather than doing your own date calculations, e.g.
%LET YYYYMM = 201501;
%put END_OF_MONTH = %sysfunc(intnx(month,%sysfunc(inputn(&YYYYMM,yymmn6.)),0,e),yymmdd10.);
Also, note that everything is text in the macro language, so you don't need to wrap text in quotes when using %sysfunc.

%sysfunc invoked functions do not require string literal arguments to be quoted. Remove the single quotes from 'MONTH'.
%let yyyymm = 201501;
%let yyyymm_date = %sysfunc(INPUTN(&YYYYMM,YYMMN6.));
%let next_month1 = %sysfunc (INTNX(MONTH,&YYYYMM_DATE,1));
%let want_yyyymm = %eval (&NEXT_MONTH1-1);
%let date9 = %sysfunc(putn(&want_yyyymm,date9.));
%let date9_literal = "&date9"d;
%put &=yyyymm;
%put &=yyyymm_date;
%put &=next_month1;
%put &=want_yyyymm;
%put &=date9;
%put &=date9_literal;
----- LOG -----
YYYYMM=201501
YYYYMM_DATE=20089
NEXT_MONTH1=20120
WANT_YYYYMM=20119
DATE9=31JAN2015
DATE9_LITERAL="31JAN2015"d
Example use of the macro variables
title "Report for month ending &date9.";
proc print data=have;
where date <= &date9_literal;
...
run;

Related

Prompt: Date, %Sysfunc(year(&myvar.));

I have a SAS EG 7.1 program that generates reports on a monthly basis. The old process was very manual, where users, amongst other things, were asked to update a macro variable (&date.) with current month-end (Date9.).
%let Date = '28feb2018'd; /* <--- Input the date to be reported */
/* Generate the year and the month based on the input date */
%let year = %sysfunc(year(&date.));
%let month = %sysfunc(month(&date.));
The &year (4-digit) and &month. (1- or 2-digit depending on the month) are later used in the code as components of a filename to pick up current month's tables:
FROM lib.great_table_loc_&year._&month.;
I am trying to make the program dynamic by prompting the user to chose the current month-end date.
The prompt is working, and outputs date9. format.
I then tried using the macro variable &Prompt_date. in the %sysfunc:
%let Date = '&prompt_date.';
%let year = %sysfunc(year(&prompt_date.));
%let month = %sysfunc(month(&prompt_date.));
When I execute, I get the following error messages:
1)
35 %let year = %sysfunc(year(&prompt_date.));
ERROR: Argument 1 to function YEAR referenced by the %SYSFUNC or
%QSYSFUNC macro function is not a number.
ERROR: Invalid arguments detected in %SYSCALL, %SYSFUNC, or %QSYSFUNC
argument list. Execution of %SYSCALL statement or %SYSFUNC
or %QSYSFUNC function reference is terminated.
36 %let month = %sysfunc(month(&prompt_date.));
ERROR: Argument 1 to function MONTH referenced by the %SYSFUNC or
%QSYSFUNC macro function is not a number.
ERROR: Invalid arguments detected in %SYSCALL, %SYSFUNC, or %QSYSFUNC
argument list. Execution of %SYSCALL statement or %SYSFUNC
or %QSYSFUNC function reference is terminated.
2)
118 lib.great_table_loc_._.
_
22
200
ERROR 22-322: Syntax error, expecting one of the following: a name, ;,
(, ',', ANSIMISS, AS, CROSS, EXCEPT, FULL, GROUP, HAVING,
INNER, INTERSECT, JOIN, LEFT, NATURAL, NOMISS, ORDER, OUTER,
RIGHT, UNION, WHERE.
ERROR 200-322: The symbol is not recognized and will be ignored.
I've tried creating a separate field for month and year, formatted to YYMMN6., input the &prompt_date. and then put(,n.) to make the value numeric - still nothing.
Has anyone encountered a similar problem?
Any tips on how to get what I want?
Thanks!
You have:
%let Date = '&prompt_date.';
%let year = %sysfunc(year(&prompt_date.));
%let month = %sysfunc(month(&prompt_date.));
Two issues.
you assign &Date but don't use it.
prompt date is DDMONYYYY (date9.). SAS will see that as a string. You need quotes and a d to make it a date.
Try
%let year = %sysfunc(year("&prompt_date."d));
%let month = %sysfunc(month("&prompt_date."d));

use a character date string as a date in data step

I have the following two macro variables:
%let start_date = 29MAY2014;
%let end_date = 15JUL2014;
I would like to create a dataset which is a series of dates between these (inclusive.) I cannot change the input format of the macro variables &start_date and &end_date.
I have tried many variations of the following, but SAS spits out an error for each:
data base_dates;
do date = put("&start_date",date9.) to put("&end_date",date9.);
output;
end;
format date date11.;
run;
Any help in this would be much appreciated
Use them as date literals, enclose in quotes and add a d at the end.
Do date = "&start_date"d to "&end_date"d;
It was simple; input() instead of put()
data base_dates;
do date = input("&start_date",date9.) to input("&end_date",date9.);
output;
end;
format date date11.;
run;

sas macro to count difference between two date strings & store the number in new variable

Parameters start_date, end_date & output_vars. Dates are charter string. How can I convert it in a macro?
data _null_;
start =;
end = ;
diff=end date-startdate;
days = intck('day',start,end);
weeks = intck('week',start,end);
months = intck('month',start,end);
year = intck('year',start,end);
put days= weeks= months= year=;
run;
First if you have macro parameters then they will be macro variables and not data step variables. So you you need to reference the parameter value as &START_DATE, etc.
Second you can use the %SYSFUNC() macro function to call the INTCK() function in macro code.
Third you need to know the date format that will be used by the parameters. It is easiest if you just request that they use DATE format, then you can use the parameter values as date literals.
%let start_date=01JAN2015 ;
%let end_date=01JAN2016 ;
%let days = %sysfunc(intck(day,"&start_date"d,"&end_date"d));

Creating a date exactly one month in the past in SAS

I am trying to create two datetime variables in SAS 9.3. The first, "endDate" is the current datetime at the time the program is run. The second, "startDate" is exactly one month in the past.
My code is:
%let endDate = %sysfunc(DATETIME() datetime.);
%let startDate = %sysfunc(intnx('month', DATETIME(), -1) datetime.);
Based on any documentation I can find, I can't figure out what is wrong with it, but I am getting the following error message:
"ERROR: Expected close parenthesis after macro function invocation not found."
What am I doing wrong?
Some additional background: I want to use these two macro variables inside a proc sql statement so I can filter a table to data from within the past month at the run-time.
Thanks!
You have a couple of issues:
%sysfunc() takes two parameters, the second one is optional, but it does need to be separated by a comma.
Your use of DateTime() function in the intnx function also requires a %sysfunc()
You have datetime variables so you need to use DTMONTH as your interval instead of month.
You don't need quotes around literals in a macro call
%let endDate = %sysfunc(DATETIME(), datetime.);
%put &endDate;
%let startDate = %sysfunc(intnx(dtmonth, %sysfunc(datetime()), -1), datetime.);
%put &StartDate;
Four things:
You don't need the single quotes around string arguments when calling functions via %sysfunc
You need to use a %sysfunc for every individual data step function you want to call in the macro environment, which means you need to nest them in this case as you're calling one function inside another. This can get messy.
You need to increment your datetime by a datetime-month increment, not a month increment, so use dtmonth instead of month.
You need a comma between the function call and the format within %sysfunc
Putting it all together:
%let endDate = %sysfunc(DATETIME(), datetime.);
%let startDate = %sysfunc(intnx(dtmonth, %sysfunc(DATETIME()), -1), datetime.);
%let endDate = %sysfunc(DATETIME(), datetime21.);
%let startDate =%sysfunc(putn(%sysfunc(intnx(dtmonth, %sysfunc(DATETIME()), -1,same)),datetime21.));
%put &enddate &startdate;

set previous month/year as macro variable in SAS

I know something like this
%let start_date = %sysfunc(intnx(day,%sysfunc(date()),-1),DATE9.);
%put &start_date;
But
%let start_month = %sysfunc(month(intnx(month,%sysfunc(date()),-1),DATE9.));
%put &start_month;
or
%let start_date = %sysfunc(intnx(month,%sysfunc(date()),-1),DATE9.);
%put %sysfunc(month(&start_date));
doesn't work.
You need another %SYSFUNC before INTNX for your example to work.
%let start_month = %sysfunc(month(%sysfunc(intnx(month,%sysfunc(date()),-1))));
%put &start_month;
However, I prefer to use DATA NULL where a lot of %SYSFUNC statements are required with %LET. The following gives you the same result.
data _null_;
call symputx('start_month ', month(intnx('month',date(),-1)));
run;
%put &start_month.;