BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
jimmychoi
Obsidian | Level 7

Hi, I recently found a strange affix for date entries in some code:

data one;
    date = '04jul2005'd;
    format date weekdate.;
run;

proc print data = one;
run;

As you see, there's a 'd' after '04jul2005'.

Since I don't recall putting that strange affix when inputting data with 'datalines' statement,

 

 

1. is it necessary to put that letter whenever with date datatypes?

2. are there anyother strange letters that comes after data?

1 ACCEPTED SOLUTION

Accepted Solutions
hashman
Ammonite | Level 13

@jimmychoiYou've already got lots of good info; I'll just fill in a few gaps.  

 

'04jul2005'd in your example is a SAS expression representing a date constant:

 

  • It's a "constant" since it's part of the program the program cannot change.   
  • It's a date constant because D after the quoted value tells the compiler to convert it - at compile time - into the respective SAS date value (i.e. 16621) using the DATEw. informat.   

In the context of your question, "compile time" is key. This is what differs a constant, as a value in source code converted during compile time, from input data interpreted by the INPUT statement (or INPUT function) at run time. For input data interpreted at run time, the D notation is unnecessary because SAS needs to know only the location, width, and informat. As constants are interpreted at compile time, there must be an instruction to the compiler as to how it should interpret their values. For SAS dates, D following a quoted character string is such an instruction. If you doubt that the conversion occurs at compile time, this may convince you:

data _null_ ;               
  put date= ;               
  stop ;                    
  retain date "04jul2005"d ;
run ;               

The SAS log shows:

date=16621       

As you see, there're no run-time statements anywhere assigning the value 16621 to DATE, and yet the PUT statement prints it. Furthermore, if you doubt that the conversion is done via the DATEw. informat, try "29feb2005"d, and the log will tell you:

ERROR 77-185: Invalid number conversion on "29febl2005"d.

There are two types of SAS constants that do not require a special suffix to be interpreted: Character and numeric, for example:

retain ch3 "ABC" ch4 "XY#Z" num1 1234 num2 123.456 ;

Some folks tend to think that character and numeric constants just get there "as is". That's wrong: No piece of raw data, whether as source code values at compile time or input data at run time, enters the SAS system without being interpreted by some kind of informat. The character and numeric constants are no exception. The former are interpreted via the CHARw.-L informat; that is, a single period isn't converted to a blank (unlike $w. does) but any leading spaces are trimmed (like $w. does do). The latter are interpreted via the BEST32. informat.

    

As to the other part of your question, there're other SAS constants requiring a specific suffix to be interpreted by the compiler:

 

1. Datetime, such as '18jan2005:9:27:05am'DT, interpreted via the DATETIMEw. informat.

2. Time, such as '9:25:19pm'T, interpreted via the TIMEw. informat.

3. Character hexadecimal, such as '2F514B'x or '2F,51,4B'x, interpreted by the $HEXw. informat (after compressing intervening commas, if any).   

4. Numeric hexadecimal, such as 0FAx or 5B2, converted via the HEXw. informat (to 250 and 1458, respectively, in this case). It should always begin with a decimal digit, or else the compiler will interpret it as a variable name. Hence, if the leading hex digit is a letter, the hex constant must be preceded by 0. Unlike with the character hex constants, commas cannot be used to separate the hex digits.   

5. Bit mask, such as '00101001'B, converted using the BINARYw. informat (to 41, in this case). This one is kind of special since it can be used only in comparisons but cannot be used to assign the converted value to a variable. (I don't know why and don't like it, but that's the way it is.)   

 

In all instances, the informat width W is set by the compiler to the actual length of a constant sans the quotes. If converted values aren't assigned to variables, they are stored internally to be used later at run time where specified in the program.     

 

Finally, there's such animal as a name literal, such as "var2"N or "My var #2"N. Though in the SAS docs it is classified as a constant, its nature has nothing in common with that of the constants described above. Its part within the quotes is simply interpreted as a variable name. If the option VALIDVARNAME=ANY is in effect, it can contain arbitrary characters. Otherwise, it must be a standard SAS name, in which case the compiler interprets "VAR"N exactly as it would just VAR (and hence there's no reason to use this N-suffix notation).

 

Paul D.  

View solution in original post

5 REPLIES 5
PaigeMiller
Diamond | Level 26

It's required in an assignment statement where you use the human readable form 04jul2005 to enter the date. It is not required if you are reading from a CARDS or DATALINES segment, as long as you have the proper informat. In fact, this suffix would be just plain wrong if a CARDS or DATALINES segment.

 

There is also the dt suffix which indicates datetime values e.g.

 

datetime='04jul2005:10:13:19'dt;

 

 

 or the t suffix which indicates you have a time value

time = '10:22:03.7't;
--
Paige Miller
ChrisNZ
Tourmaline | Level 20

And also x n and b.  See here.

data _null_;  
  x = '09'x ;
  if 'x'n = '00001001'b then putlog 'Tab'; 
run;

Tab

Cynthia_sas
SAS Super FREQ

Hi:

  To provide you with a concrete example of DATALINES not needing the 'D and a specific example of usages where you DO need the 'D, here's an example:

example_dates_both_forms.png

 

As you can see, in the DATALINES, the dates are "readable" dates. I use an informat to convert them, internally, into the number of days since Jan 1, 1960, which is how SAS stores date values. But if I want to find out how old someone will be on 31Aug2018, then I have to turn 31Aug2018 (the readable date) into the number of days since Jan 1, 1960 (that internal value is 21427 for 31Aug2018) so that the subtraction and division can take place for the calculation. (And yes, I know I could have used a fancier function to calculate age -- this is my simple math example.)

 

  So that is one way to use a date constant in a program -- not for reading a date value, but for specifying a date value as a constant, so SAS can convert it to the number of days since Jan 1, 1960.

 

  Another way to use the date constant is to use it in a WHERE statement (or IF statement), where I want to filter the data so I only see the rows for people born AFTER Jan 1, 1983 -- I don't want to count up to find out that the internal value for Jan 1, 1983 is 8401.

  For something fun, find out your SAS date value as the number of days since Jan 1, 1960 with this little program:


data mybday;
  mybday = 'ddmmmyyyy'd;
  putlog '----->My Birthday is:' ;
  putlog 'Internal value ' mybday=;
  putlog 'Formatted value ' mybday= worddate.;
run;

Replace the ddmmmyyyy with your birthday and then look in the log. Negative numbers for internal value mean you were born BEFORE Jan 1, 1960 and positive numbers mean you were born AFTER Jan 1, 1960 (and, of course, 0 means you were born ON Jan 1, 1960).

 

Cynthia

Tom
Super User Tom
Super User

That is a date literal.  The D tells the SAS compiler that it is DATE literal and NOT a string literal.

Date literals must be in a format that the DATE informat understands.  Example:  '1jan2018'd , '01-JAN-18'D

 

The D is required, otherwise SAS will think you just want a character string, just because it looks to humans like a date does not mean that the SAS compiler will know that. The D is what tells it that the quoted characters represent a date.

 

Note if you also leave off the quotes then SAS will not like it either as then it is neither a valid number or a valid variable name, since it starts with a digit.

 

You do NOT include the quotes and the letter D in data that you are reading using a INFORMAT since that is not a literal value. It is just a string of characters that you are reading. 

 

The SAS documentation is inconsistent in what it calls these.  In some places they are called constants and in others they are called literals.  The only place I was able to find a summary is where there are telling why you should not follow a string literal with a letter because then SAS might think that you meant some other type of literal instead of just a string literal.

 

Characters That Follow a Character Constant
Possible Interpretations
Examples
b
bit testing constant
'00100000'b
d
date constant
'01jan04'd
dt
datetime constant
'18jan2005:9:27:05am'dt
n
name literal
'My Table'n
t
time constant
'9:25:19pm't
x
hexadecimal notation
'534153'x
hashman
Ammonite | Level 13

@jimmychoiYou've already got lots of good info; I'll just fill in a few gaps.  

 

'04jul2005'd in your example is a SAS expression representing a date constant:

 

  • It's a "constant" since it's part of the program the program cannot change.   
  • It's a date constant because D after the quoted value tells the compiler to convert it - at compile time - into the respective SAS date value (i.e. 16621) using the DATEw. informat.   

In the context of your question, "compile time" is key. This is what differs a constant, as a value in source code converted during compile time, from input data interpreted by the INPUT statement (or INPUT function) at run time. For input data interpreted at run time, the D notation is unnecessary because SAS needs to know only the location, width, and informat. As constants are interpreted at compile time, there must be an instruction to the compiler as to how it should interpret their values. For SAS dates, D following a quoted character string is such an instruction. If you doubt that the conversion occurs at compile time, this may convince you:

data _null_ ;               
  put date= ;               
  stop ;                    
  retain date "04jul2005"d ;
run ;               

The SAS log shows:

date=16621       

As you see, there're no run-time statements anywhere assigning the value 16621 to DATE, and yet the PUT statement prints it. Furthermore, if you doubt that the conversion is done via the DATEw. informat, try "29feb2005"d, and the log will tell you:

ERROR 77-185: Invalid number conversion on "29febl2005"d.

There are two types of SAS constants that do not require a special suffix to be interpreted: Character and numeric, for example:

retain ch3 "ABC" ch4 "XY#Z" num1 1234 num2 123.456 ;

Some folks tend to think that character and numeric constants just get there "as is". That's wrong: No piece of raw data, whether as source code values at compile time or input data at run time, enters the SAS system without being interpreted by some kind of informat. The character and numeric constants are no exception. The former are interpreted via the CHARw.-L informat; that is, a single period isn't converted to a blank (unlike $w. does) but any leading spaces are trimmed (like $w. does do). The latter are interpreted via the BEST32. informat.

    

As to the other part of your question, there're other SAS constants requiring a specific suffix to be interpreted by the compiler:

 

1. Datetime, such as '18jan2005:9:27:05am'DT, interpreted via the DATETIMEw. informat.

2. Time, such as '9:25:19pm'T, interpreted via the TIMEw. informat.

3. Character hexadecimal, such as '2F514B'x or '2F,51,4B'x, interpreted by the $HEXw. informat (after compressing intervening commas, if any).   

4. Numeric hexadecimal, such as 0FAx or 5B2, converted via the HEXw. informat (to 250 and 1458, respectively, in this case). It should always begin with a decimal digit, or else the compiler will interpret it as a variable name. Hence, if the leading hex digit is a letter, the hex constant must be preceded by 0. Unlike with the character hex constants, commas cannot be used to separate the hex digits.   

5. Bit mask, such as '00101001'B, converted using the BINARYw. informat (to 41, in this case). This one is kind of special since it can be used only in comparisons but cannot be used to assign the converted value to a variable. (I don't know why and don't like it, but that's the way it is.)   

 

In all instances, the informat width W is set by the compiler to the actual length of a constant sans the quotes. If converted values aren't assigned to variables, they are stored internally to be used later at run time where specified in the program.     

 

Finally, there's such animal as a name literal, such as "var2"N or "My var #2"N. Though in the SAS docs it is classified as a constant, its nature has nothing in common with that of the constants described above. Its part within the quotes is simply interpreted as a variable name. If the option VALIDVARNAME=ANY is in effect, it can contain arbitrary characters. Otherwise, it must be a standard SAS name, in which case the compiler interprets "VAR"N exactly as it would just VAR (and hence there's no reason to use this N-suffix notation).

 

Paul D.  

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

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