I'm trying to convert a date field from date9. format to a character field and it's not working for single digit dates.
so for example:
qsdate = 09OCT2023
Using my code of
new_date = put(qsdate , day2.) || ' ' || propcase(put(qsdate ,monname3.)) || ' ' || put(qsdate , year4.);
returns a value of 9 Oct 2023
What am I missing to get the leading zero?
Why not just use the DATE9. format.
To get leading zero use the Z format.
Note to put spaces between the values use CATX() function.
data test;
qsdate = '09OCT2023'd;
date_char = put(qsdate,date9.);
date_char2 = catx(' ',put(day(qsdate),z2.),propcase(put(qsdate,monname3.)),year(qsdate));
date_char3 = catx(' ',substr(date_char,1,2),propcase(substr(date_char,3,3)),substr(date_char,6));
put (_all_) (=/);
run;
qsdate=23292 date_char=09OCT2023 date_char2=09 Oct 2023 date_char3=09 Oct 2023
Why not just use the DATE9. format.
To get leading zero use the Z format.
Note to put spaces between the values use CATX() function.
data test;
qsdate = '09OCT2023'd;
date_char = put(qsdate,date9.);
date_char2 = catx(' ',put(day(qsdate),z2.),propcase(put(qsdate,monname3.)),year(qsdate));
date_char3 = catx(' ',substr(date_char,1,2),propcase(substr(date_char,3,3)),substr(date_char,6));
put (_all_) (=/);
run;
qsdate=23292 date_char=09OCT2023 date_char2=09 Oct 2023 date_char3=09 Oct 2023
Create a custom format using "directives" in PROC FORMAT PICTURE statement that produces the desired formatted output. This enables you to control the exact appearance of the output. I always think that taking date values and pulling them apart with character functions is a sub-optimal approach. And why do you need this as character anyway, unless it is for use in a title or label, leaving the date as numeric (with whatever format you want) is a better approach because then dates will sort in the expected order; while character dates will not sort in order and the first day of the year 2023 is 01 Apr 2023.
data have;
date='09OCT2023'd;
run;
proc format;
picture myfmt low-high='%0d %3b %Y' (datatype=date);
run;
data want;
set have;
chardate=put(date,myfmt12.);
run;
Picture formats are nice. There does not appear to be a picture element for printing the MONTH name in Propercase however.
When playing around with trying to use SUBSTR() and PROPCASE() to update the result I was confused at first until I realized you had made the format width one byte too long in your example data step and the PUT was right aligning the values (so adding an extra space at the beginning).
You can prevent that in this case by being specific when you DEFINE the format.
picture myfmt(default=11 max=11 min=11) low-high='%0d %3b %Y' (datatype=date);
Then if you try to use an invalid width on the format specification you will get an error message.
Example:
1 proc format; 2 picture myfmt low-high='%0d %3b %Y' (datatype=date); NOTE: Format MYFMT has been output. 3 run; NOTE: PROCEDURE FORMAT used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 4 data _null_; 5 date='09MAR2023'd; 6 chardate=put(date,myfmt12.); 7 put date= chardate=$quote.; 8 run; date=23078 chardate=" 09 MAR 2023" NOTE: DATA statement used (Total process time): real time 0.01 seconds cpu time 0.01 seconds 9 proc format; 10 picture myfmt(default=11 max=11 min=11) low-high='%0d %3b %Y' (datatype=date); NOTE: Format MYFMT is already on the library WORK.FORMATS. NOTE: Format MYFMT has been output. 11 run; NOTE: PROCEDURE FORMAT used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 12 data _null_; 13 date='09MAR2023'd; 14 chardate=put(date,myfmt12.); -------- 29 ERROR 29-185: Width specified for format MYFMT is invalid. 15 put date= chardate=$quote.; 16 run; NOTE: The SAS System stopped processing this step because of errors. NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.01 seconds
Picture formats are nice. There does not appear to be a picture element for printing the MONTH name in Propercase however.
Actually %3b capitalizes the first letter of the month and the next 3 are lower case.
@PaigeMiller wrote:
Picture formats are nice. There does not appear to be a picture element for printing the MONTH name in Propercase however.
Actually %3b capitalizes the first letter of the month and the next 3 are lower case.
Not in the code I posted before.
1 proc format; 2 picture myfmt low-high='%0d %3b %Y' (datatype=date); NOTE: Format MYFMT is already on the library WORK.FORMATS. NOTE: Format MYFMT has been output. 3 run; NOTE: PROCEDURE FORMAT used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 4 data _null_; 5 date='09MAR2023'd; 6 chardate=put(date,myfmt12.); 7 put date= chardate=$quote.; 8 run; date=23078 chardate=" 09 MAR 2023" NOTE: DATA statement used (Total process time): real time 0.01 seconds cpu time 0.01 seconds
Mixed case on SODA.
1 %put &=sysvlong; SYSVLONG=9.04.01M7P080620 2 proc format; 3 picture myfmt low-high='%0d %3b %Y' (datatype=date); NOTE: Format MYFMT is already on the library WORK.FORMATS. NOTE: Format MYFMT has been output. 4 run; NOTE: PROCEDURE FORMAT used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 5 data _null_; 6 date='09MAR2023'd; 7 chardate=put(date,myfmt12.); 8 put date= chardate=$quote.; 9 run; date=23078 chardate=" 09 Mar 2023" NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds
Upper case on PC SAS
1 %put &=sysvlong; SYSVLONG=9.04.01M7P080520 2 proc format; 3 picture myfmt low-high='%0d %3b %Y' (datatype=date); NOTE: Format MYFMT is already on the library WORK.FORMATS. NOTE: Format MYFMT has been output. 4 run; NOTE: PROCEDURE FORMAT used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 5 data _null_; 6 date='09MAR2023'd; 7 chardate=put(date,myfmt12.); 8 put date= chardate=$quote.; 9 run; date=23078 chardate=" 09 MAR 2023" NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.01 seconds
Was there a bug fix between those two minor,minor release numbers?
9.04.01M7P080620 vs
9.04.01M7P080520
The documentation says %3b produces upper case first letter and lower case remaining letters, and when I ran my code, the output was what the documentation said.
Quote:
Tip | For the English language, use the directive %3B to create an abbreviated month with only an uppercase initial letter (for example, Jan). |
---|
So if you aren't using English it doesn't work for you, or there is a bug when you ran it.
You left out the key detail. It depends on the ENCODING that your session is using.
Multi Byte
1 proc format; 2 picture single_byte (default=11) low-high='%0d %3B %Y' (datatype=date); NOTE: Format SINGLE_BYTE has been output. 3 picture multi_byte (default=11) low-high='%0d %3b %Y' (datatype=date); NOTE: Format MULTI_BYTE has been output. 4 run; NOTE: PROCEDURE FORMAT used (Total process time): real time 0.00 seconds cpu time 0.00 seconds 5 data _null_; 6 date='09MAR2023'd; 7 encoding=getoption('encoding'); 8 put encoding= 9 / 'Single Byte ' date single_byte. 10 / 'Multi Byte ' date multi_byte. 11 ; 12 run; encoding=UTF-8 Single Byte 09 March 20 Multi Byte 09 Mar 2023 NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.01 seconds
Single Byte
1 proc format; 2 picture single_byte (default=11) low-high='%0d %3B %Y' (datatype=date); NOTE: Format SINGLE_BYTE is already on the library WORK.FORMATS. NOTE: Format SINGLE_BYTE has been output. 3 picture multi_byte (default=11) low-high='%0d %3b %Y' (datatype=date); NOTE: Format MULTI_BYTE is already on the library WORK.FORMATS. NOTE: Format MULTI_BYTE has been output. 4 run; NOTE: PROCEDURE FORMAT used (Total process time): real time 0.01 seconds cpu time 0.01 seconds 5 data _null_; 6 date='09MAR2023'd; 7 encoding=getoption('encoding'); 8 put encoding= 9 / 'Single Byte ' date single_byte. 10 / 'Multi Byte ' date multi_byte. 11 ; 12 run; encoding=WLATIN1 Single Byte 09 Mar 2023 Multi Byte 09 MAR 2023 NOTE: DATA statement used (Total process time): real time 0.00 seconds cpu time 0.00 seconds
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
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.
Ready to level-up your skills? Choose your own adventure.