BookmarkSubscribeRSS Feed
MinnaG
Calcite | Level 5

Hi, can someone explain the following to me:

 

I have a macro variable (obviously holds a string) assigned a date,

%let sysparm=230524;
%put &sysparm.;

The log: 

27         
28         %let sysparm=230524;
29         %put &sysparm.;
230524
30 

Then I have the following datastep

data a;
new=&sysparm.;
run;

 

which results in the following table

image.png

 

What I don't understand is why the datastep converts the content of my macro variable (which is a string) to a numeric variable. Can someone explain to me why the variable new is now a numeric variable?

5 REPLIES 5
yabwon
Amethyst | Level 16

Macro language is a code generating language. Every value of macrovariable is a text. That is why you have to use functions like %eval() to "add two macrovariables" e.g. (the log):

 

1    %let a=1;
2    %let b=2;
3
4    %put **%eval(&a+&b)**;
**3**
5    %put **&a+&b**;
**1+2**

 

 

When you are a "rookie" SAS programer, you write simple 4GL data step like:

 

data a;
  b=42;
run;

and think like this:

- first step is compilation phase (SAS checks syntax, recognise 42 as a number and makes 'b' numeric) and

- the second is execution phase (SAS runs the code, so create dataste 'a' with vriable 'b' with value 42).

 

But that in fact is not the case. Before the "first" step there is one more, we may call it "step" zero.

 

Step "zero" is the moment when text (literally) of your program is parsed by the Macro processor. Macro processor scans the text, looks for all macro elements, resolves them and only the push the code to compiler.

So you start with:

%let MV=42;
data a;
  b=&MV;
run;

Macro processor see first line and creates macrovariable (in the macrovariables table), so the text looks now like:

data a;
  b=&MV;
run;

M.p. looks at "new firs line" and see ordinary 4GL code, next looks at line 2 and see call for resolution to macrovariable MV (&MV) so looks intl macrovariable table and replace the "&MV" text with "42", in the line 3 M.p. reach the end of the data step, the code looks now:

data a;
  b=42;
run;

and this is the moment when compilation phase of that data step starts (so the "first")

 

Here are links to the documentation:

1) How SAS _Processes_ Statements with Macro Activity:
https://documentation.sas.com/?docsetId=mcrolref&docsetTarget=p0znr2zp0ubdzjn10wmhw0y2ef1q.htm&docse...

2) How the Macro Processor _Compiles_ a Macro Definition:
https://documentation.sas.com/?docsetId=mcrolref&docsetTarget=p06bq1j5uf0sz4n1vd3wx36tf0ud.htm&docse...

3) How the Macro Processor _Executes_ a Compiled Macro"
https://documentation.sas.com/?docsetId=mcrolref&docsetTarget=p0eksviivbw6bwn1eg6h2crvl7ct.htm&docse...

 

 

Bart

 

 

 

 

 

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



Tom
Super User Tom
Super User

You used the macro variable to generate code.

new=&sysparm.;

Once the macro processor had finished expanding the macro variable reference it passed the result onto SAS to interpret.  So SAS sees this statement:

new=230524;

Which is how you assign the number 203,524 to a variable named NEW.

 

If you want the macro processor to generate a text string then you need quotes. You can either add them into the value of the macro variable.

%let sysparm="230524";

Or add them in the SAS code

new="&sysparm.";

You could also just use the SYMGET() function to return the value of the macro variable as a string.  It wants the name of the macro to look for as a string.

new=symget('sysparm');
ballardw
Super User

@MinnaG wrote:

Hi, can someone explain the following to me:

 

I have a macro variable (obviously holds a string) assigned a date,

%let sysparm=230524;
%put &sysparm.;

My first comment is that I had to look very hard at that nearly random string of digits to determine the "dateness". It not obvious at all. Years should be 4 digits at least.  That value could be either 23 May 2024 (or 1924 or ...) or 24 May 2023 (or 1923 or ...).

So is a relatively poor choice for use in code as a date.

Second, SAS date values are numeric. They are the number of days from  1 Jan 1960. So you want a properly valued date value for way more things than characters that look like that. Quick, how many days between 220222 and 230524? SAS provides functions to work with date values that return such bits of information. Plus the various date formats allow you do many things without manipulating the underlying date values for reporting and analysis.

I suggest that you think of date values in SAS programming as such and not characters.

 

A brief example of using different formats for a given date value. Note the Today() function to get the date value for the day the program runs. This writes that date to the log in several different formats, including what I think is your 6-digit appearance:

data example;
   x= today();
   put "Date9 format: " x=date9.;
   put 'YYMMDD10 format:' x=yymmdd10.;
   put 'mmddyy10 format:' x=mmddyy10.;
   put 'YYQ format:' x=yyq.;
   put 'Monname format:' x=monname.;
   put 'MONyy format:' x=MONyy.;
   put 'MONyy7 format:' x=MONyy7.;
   put 'yymmddn6 format:' x=yymmddn6.;
run;

You can even create custom formats with Proc Format to create appearance involving date elements.

I didn't go into the day of week or week of year at all plus the ISO type values.

 

https://communities.sas.com/t5/SAS-Communities-Library/Working-with-Dates-and-Times-in-SAS-Tutorial/... has a PDF with much information about dates.

 

Patrick
Opal | Level 21

Others already explained that the macro variable resolves first and SAS data step compilation then just sees the resolved value. 

For your sample I guess what would be best is for the value of the macro variable to map into a numerical variable with a SAS date value. Below how this can be achieved.

%let sysparm=230524;
%put &sysparm.;

data sample;
  format dt date9.;
  dt=input("&sysparm",yymmdd8.);
run;

proc print data=sample;
run;

Patrick_0-1685155166854.png

Conversion to a SAS Date value will allow you to use SAS calendar functions like intnx() and intck() or also to simply substract "date" variables from each other. 
A SAS Date value is the count of days since 1/1/1960, stored in a numerical variable. The format applied (above date9.) prints such a value in a human readable form.

Kurt_Bremser
Super User

Since the text (!) inserted by the macro processor is not enclosed in quotes, and constitutes a valid number according to SAS syntax rules, the variable on the left of the assignment is created as numeric.

 

You want 230524 to be handled as a date; which date? Is it 2023-05-24, 2024-05-23, 1924-05-23, or any other possible date built with those numbers between the years 1582 and 9999? I hope you realize the plain stupidity of using 2-digit years now. Also google "Y2K", if you're younger than 25.

 

To store a text string as a date, you need to convert it to such:

%let sysparm = 20230524;

data a;
new = input("&sysparm.",yymmdd8.);
format new yymmdd10.;
run;

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

Creating Custom Steps in SAS Studio

Check out this tutorial series to learn how to build your own steps in SAS Studio.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 1716 views
  • 3 likes
  • 6 in conversation