DATA Step, Macro, Functions and more

Using the today() function in a data null step.

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 14
Accepted Solution

Using the today() function in a data null step.

Hi All,

 

I am having an error when trying to run this code:

 

%let bcfdate = today();

%let days = 8;

 

data _null_;

%let bcfstart=%sysfunc(intnx("day",%sysfunc(&bcfdate.),-&days.));

run;

%put &bcfstart.;

 

I believe that the today() function cannot be processed in the data _null_ statement and therefore "bcfstart" cannot be calculated

 

Does anyone have any ideas on how to get around this issue?

Cheers.


Accepted Solutions
Solution
‎05-23-2017 07:08 AM
PROC Star
Posts: 551

Re: Using the today() function in a data null step.

I believe this is what you want and a bit simpler

 

%let days = 8;

data _null_;
	format bcfstart date9.;
	bcfstart=intnx("day",today(),-&days.);
	put bcfstart;
run;


View solution in original post


All Replies
Super User
Posts: 5,256

Re: Using the today() function in a data null step.

Why are you storing today() in a macro variable?

If this is the first thing that happens in your session, use "&Sysdate"d instead.

Also, %sysfunc should be used in open code, not within a data step.

Please look at more examples on how to use %sysfunc, intnx, today() etc.

Data never sleeps
Solution
‎05-23-2017 07:08 AM
PROC Star
Posts: 551

Re: Using the today() function in a data null step.

I believe this is what you want and a bit simpler

 

%let days = 8;

data _null_;
	format bcfstart date9.;
	bcfstart=intnx("day",today(),-&days.);
	put bcfstart;
run;


Super User
Posts: 6,936

Re: Using the today() function in a data null step.

A macro statement is resolved before the other SAS code is interpreted. So the data step ends up as

data _null_;
run;

which is, of course, totally useless.

So let's look at the macro statement that you wrote into the data step code (not into the data step, mind!).

After resolution of the two macro variables, we get

%let bcfstart=%sysfunc(intnx("day",%sysfunc(today()),-8));

Note that you wrote "day", not day without quotes. The macro processor knows only one datatype, text, and therefore does not need quotes around strings. If quotes are used, they become part of the string, so what is fed to the datastep function within the %sysfunc will appear as

intnx('"day"',

which is invalid syntax and gets you a

WARNING: Argument 1 to function INTNX referenced by the %SYSFUNC or %QSYSFUNC macro function is out of range.

which basically says it all.

Maxim 2: Read the LOG.

 

If you want to do your calculation in a data step (for easier reading), do this:

%let bcfdate = %sysfunc(today());
%let days = 8;

data _null_;
bcfstart = intnx("day",&bcfdate.,-&days.);
call symput('bcfstart',put(bcfstart,best.));
run;

%put &bcfstart.;

You will see that &bcfstart now contains the raw value for the intended date, which is perfectly fine for date calculations later in the code.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Occasional Contributor
Posts: 14

Re: Using the today() function in a data null step.

Thanks for your solution.

 

Is this a local macro variable?

 

It is just that I need to use this in a title as follows:

 

title3 "Date range &bcfstart to &bcfend";

 

And SAS does not seem to pick up these macros.

Thanks.

PROC Star
Posts: 1,231

Re: Using the today() function in a data null step.

You may not need macro variables at all.  Some folks feel pure macro code can be hard to read.  But I don't mind it.

 

You can code:

101  %put %sysfunc(intnx(day,%sysfunc(today()),-8),mmddyy10);
05/15/2017
102  %put %sysfunc(intnx(day,%sysfunc(today()),8),mmddyy10);
05/31/2017

 

If you want macro variables for bcfdate and day, just make sure bcfdate is assigned a SAS date value, e.g.:

103  %let bcfdate=%sysfunc(today());
104  %let days=8;
105  %put %sysfunc(intnx(day,&bcfdate,-&days),mmddyy10);
05/15/2017
106  %put %sysfunc(intnx(day,&bcfdate,&days),mmddyy10);
05/31/2017

You can use that in a title statement as well:

 

title3 "Date range %sysfunc(intnx(day,&bcfdate,-&days),mmddyy10) to %sysfunc(intnx(day,&bcfdate,&days),mmddyy10)";

 

And if you really wanted to, you could make a little macro function to do the work for you.  Some would say that is overkill.  But if you need to create relative dates often, it might make sense.  Peter Crawford has a great paper on a %now macro:

http://www2.sas.com/proceedings/sugi31/038-31.pdf

Super User
Super User
Posts: 7,401

Re: Using the today() function in a data null step.

 

data _null_;
  call execute(cat('title3 "Date range ',put(date(),date9.),' to ',put(date()+8,date9.),'";'));
run;

Or if you really want to use macro variables:

data _null_;
  call symputx('title',(cat('title3 "Date range ',put(date(),date9.),' to ',put(date()+8,date9.),'";')));
run;

 

 

Super User
Posts: 6,936

Re: Using the today() function in a data null step.


PriyaL wrote:

Thanks for your solution.

 

Is this a local macro variable?

 

It is just that I need to use this in a title as follows:

 

title3 "Date range &bcfstart to &bcfend";

 

And SAS does not seem to pick up these macros.

Thanks.


Any macro variable created inside a macro will be in the local macro table and vanish after the macro has executed. Only variables that already existed in the global table, or were created with call symputx and the 'g' option, or named in a %global statement will be global.

 

So it depends on where you create the macro variables.

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Super User
Super User
Posts: 6,500

Re: Using the today() function in a data null step.

[ Edited ]

If you used the code in the answered that is marked as correct there is no macro variable created by that code. You could add a CALL SYMPUTX() statement to make one if you want.  

 

Note that SAS dates are number of days. So no need to use the INTNX() function to add/subtract days.

You can use the automatic macro variable SYSDATE9 which should have the date the SAS session started in DATE9 format.  If you have long running sessions that could span multiple days and you really need the date that this block of code started then you could use the DATE() function (or it's alias the TODAY() function).

%let bcfend = &sysdate9;
%let days = 8;
data _null_;
  call symputx('bcfstart',put("&bcfend"d - &days,date9.));
run;
title3 "Date range &bcfstart to &bcfend";

 If you are running inside of a macro that is ended before your TITLE statement runs then you might need to add the optional third parameter to make sure it generates a GLOBAL macro variable.  Without that if the macro variable does not already exist then CALL SYMPUTX() will make it in the symbol table for the macro and it will disappear when the macro finishes running.

Super User
Super User
Posts: 7,401

Re: Using the today() function in a data null step.

Doesn't make sense on several levels.  First today() is a base SAS function you can use anywhere, creating a macro variable doesn't make sense here as you can just replace that macro variable with today().  A simple way of doing this is:

data _null_;
  call symputx('bcfstart',today()+8;
run;

Although there really isn't a point in that either as you can just put: today()+8 anywhere you need it for the same effect - i.e. creating code for no reason.

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 9 replies
  • 226 views
  • 2 likes
  • 7 in conversation