How to format input for SAS's MONYY format - date

I currently have a dataset with dates in the format "FY15 FEB". In attempting to format this variable for use with SAS's times and dates, I've done the following:
data temp;
set pre_temp;
yr = substr(fiscal,3,2);
month = substr(fiscal,6,length(fiscal));
mmmyy = month||yr;
input mmmyy MONYY5.;
datalines;
run;
So, I have the strings representing the year and corresponding month. However, running this code gives me the error "The informat $MONYY was not found or could not be loaded." Doing some background on this error tells me that it has something to do with passing the informat a value with the wrong type; what should I alter in order to get the correct output?
*Edit: I see on the SAS support page for formats that "MONYYw. expects a SAS date value as input;" given this, how do I go from strings to a different date format before this one?

When you see a $, it means character value. In this case, you're feeding SAS a character value and giving it a numeric format. SAS inserts the $ for you, but there is no such format in existence.
I'm going to ignore the datalines statement, because I'm not sure why it's there (though I do notice there is no set statement). You might have an easier time just changing your program to:
data temp;
yr = substr(fiscal,3,2);
month = substr(fiscal,6,length(fiscal));
pre_mmmyy = strip(month)||strip(yr);
mmmyy=input(pre_mmmyy,MONYY5.);
run;
you can also remove the "length(fiscal))" from the substring function. The 3rd argument to the substring function is optional, and will go to the end of the string by default.

Related

SAS change date format

I want to define a date format that takes the following format : 12JAN2010
I tried using this code :
/* partie B question 2*/
data projet.Ophtalmo_new;
set projet.Ophtalmo_new (RENAME=(date_diagnostic=date_dia)) (RENAME=
(date_examen=date_exa));
date_diagnostic = input (date_dia, DDMMYY10.);
date_examen = input (date_exa, DDMMYY10.);
format date_diagnostic date_examen date9.;
run;
But it sends me the following syntax error :
ERROR 22-322: Syntax error, expecting one of the following: un nom, une chaƮne
entre guillemets, ;,
CUROBS, END, INDSNAME, KEY, KEYRESET, KEYS, NOBS, OPEN, POINT,
_DATA_, _LAST_, _NULL_.
I'm still a sas beginner and i can't manage to get it to work properly, hope you can help, thanks.
The syntax for data set options is a single parenthetical expression. The rename option fits within:
data-set-name ( ... options ... rename=(...) );
The syntax of the RENAME option is the following:
rename=(old-name-1=new-name-1 old-name-2=new-name-2 ...)
So the correct set statement would be
set projet.Ophtalmo_new (RENAME=(date_diagnostic=date_dia date_examen=date_exa));
Because you state your are a beginner I added this section.
The code you show indicates input of the variables originally named date_diagnostic and date_examen. If these variables are indeed character variables to start, then the input is necessary to convert from character to a SAS date (which is simply a number with special meaning). If, however, the variables were already a SAS date with a format different than the one you want, you only need to update the format of the variables (or use a FORMAT statement to change the format to use during a PROC step)
data have;
x = '01-jan-2017'd;
format x ddmmyy10.;
run;
* demonstrate that the permanent format of x is ddmmyy10.;
data _null_;
put x=;
run;
* demonstrate temporary formatting of variable during step;
data _null_;
set have;
format x date9.; * modify the format temporarily during execution of data _null_;
put x=;
run;
* permanently change format of variable;
* only the dataset metadata (or header data) changes, the entire data set is NOT rewritten;
proc datasets nolist lib=work;
modify have;
format x date9.;
run;
* demonstrate that the permanent format of x has changed to date9.;
data _null_;
set have;
put x=;
run;
I believe the issue is the RENAME statement. You can only call it once.
Change this:
set projet.Ophtalmo_new (RENAME=(date_diagnostic=date_dia)) (RENAME=
(date_examen=date_exa));
to this:
set projet.Ophtalmo_new (RENAME=(date_diagnostic=date_dia date_examen=date_exa));
You can't rename the dates and then use those variables in your INPUT statement. They've been renamed and no longer exist, so trying to access date_dia in the INPUT function will at worst result in all missing values.
You also shouldn't use the notation of having the same data set name in your DATA and SET statement. This means once this step is run, the original data no longer exists. So you need to back up several steps and recreate your original data first before you can even fix your code. In general, this leads to errors that are harder to diagnose and fix because even if you fix your code your original data is wrong so you still think you have errors.
So, changes:
1. Change name of output data set in data statement.
2. Remove RENAME data set options.
3. Add DROP statement to remove the variables no longer desired.
/* partie B question 2*/
data projet.Ophtalmo2;
set projet.Ophtalmo_new;
date_diagnostic = input (date_dia, DDMMYY10.);
date_examen = input (date_exa, DDMMYY10.);
format date_diagnostic date_examen date9.;
drop date_dia date_exa;
run;

SAS: Get current year in YY format

I want to assign the current year in a YY format to either a macro or data set variable.
I am able to use the automatic macro variables &sysdate or &sysdate9 to get the current date. However, extracting the year in a YY format is proving to be a nightmare. Below are some examples of what I've been trying.
There exists the YEARw. format. But when I try to use it I get errors or weird results. For instance, running
data _null_;
yy = year(input("&sysdate9.", year2.));
put yy=;
run;
produces the error
ERROR 48-59: The informat YEAR was not found or could not be loaded.
If I try to format the variable in the output, I get 1965 instead of the current year. The following
data _null_;
yy = year(input("&sysdate9.", date9.));
put yy= yy year2.;
run;
outputs
yy=2016 65
Please help.
This works to get you the 2-digit year number of the current year:
DATA _NULL_;
YEAR = PUT(TODAY(),YEAR2.);
PUT YEAR;
RUN;
/* Returns: 16 */
To breakdown what I am doing here:
I use TODAY() to get the current date as a DATE type. &SASDATE needs to be converted to a DATE, but also it is the date that the SAS session started. TODAY() is the current date.
PUT allows us to pass in a non-character (numeric/date) value, which is why it is used with TODAY() as opposed to INPUT.
I think it is worth exploring the issues here in more detail.
First, Formats are patterns for converting numeric values to a human readable format. That's what you want to do here: convert a date value to a human readable format, in this case to a year.
Informats, on the other hand, convert human readable information to numeric values. That's not what you're doing here; you have a value already.
Second, put matches with Formats, and input matches with informats, exclusively.
Third, you get close in your last try: but you misuse the year format. Formats are basically value mappings, so they map every possible numeric value in their range (sometimes "all values" is the range, sometimes not) to a display value (string). You need to know what kind of value is expected on the input. YEARw. expects a date value as input, not a year value: meaning input is "number of days from 1/1/1960", mapped to "year". So you cannot take a value you've already mapped to a year value and map it again with that method; it will not make any sense.
Let's look at it:
data _null_;
yy = year(input("&sysdate9.", date9.));
put yy= yy year2.;
run;
yy contains the result of the year function - 2016. Good so far. Now, you need the 2 digit year (16); you can get that through mod function, if you like, or put/substr/input:
data _null_;
yy = input(substr(put(year(input("&sysdate9.", date9.)),4.),3,2),2.);
put yy=;
run;
mod is probably easier though since it's a number. But of course you could've used year:
data _null_;
yy = put(input("&sysdate9.", date9.),year2.);
put yy=;
run;
Now, yy is character, so you could wrap that with input(...,2.) or leave it character depending on your purposes.
Finally - a use note on &sysdate9.. You can easily make this a date without input:
"&sysdate9."d
So:
yy = put("&sysdate9."d,year2.);
That's called a date literal (and "..."dt and "..."t also work for datetime,time). They require things in the standard SAS formats to work properly.
And as pointed out in Nicarus' answer, today() is a bit better than &sysdate9 since it is guaranteed to be today. If you're running this in batch or restart your session daily, this won't matter, but it will if you have a long-running session.
Apply the year function to the date variable
Convert to string
Take last 2 digits
EDIT: change input to PUT
Year = substr(put(year(today()), 4.), 3);

Failed to change character into date in SAS

I imported 5 excel files into SAS and there are some dates formatted as 8/3/1989 originally and formatted into 03Aug1989 (DATE9.) which is what I really want. However, on 1 file the dates failed to converted into DATE9. and it is read as $CHAR10 when I read the log. I tried several ways to reformat it into DATE9 but failed.
I tried to change all informat/format/input into DATE9. instead of $CHAR10 but failed, the results are all empty (.)
I tried DateNew=input (Date,DATE9.); but it didn't work either.
Any comment?
Thanks!
Joe's suggestion in the comment should be plan A. But occasionally built-in SAS format-specifying options don't work and you still end up with a string. If that's where you're at, here's a good fallback:
data test;
format imported_date $char10.;
imported_date = "8/3/1989";
month = scan(imported_date, 1, "/")*1;
day = scan(imported_date, 2, "/")*1;
year = scan(imported_date, 3, "/")*1;
date_datefmt = mdy(month,day,year);
format date_datefmt date9.;
run;

Converting SAS Character of form "mo-yr" to a SAS date

I'm trying to convert a SAS string of the form "MO-YR" (e.g. "Jan-04") to a SAS date.
Unfortunately, I don't think there is a date format in SAS that takes that form, so I can't just use an input statement like this date = input(datestring, sasformat).
I've been using this site to find date formats: http://v8doc.sas.com/sashtml/lrcon/zenid-63.htm
Thanks,
Michael
MONYY seems to work for me.
data _null_;
input #1 mydate monyy6.;
put mydate= date9.;
datalines;
Jan-04
Dec-12
;;;;
run;
Puts the correct values to the log.

Conversion of SAS Macro Variable to time stamp

I am trying to convert SAS Macro variable to timestamp and stumped while conversion. The code which I am using is given below.
%let date = '03/15/2013';
%put %sysfunc(inputn(&date,datetime26.6));
Error which I am getting is
WARNING: Argument 1 to function INPUTN 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.
Please let me know if someone knows answers to this.
That is not a DATETIME, that is a DATE format (to INPUT, which depends on the incoming data, not the outgoing). You also need to remove the quotes, SYSFUNC treats quotes as characters, not as string delimiters.
%let date = 03/15/2013;
%put %sysfunc(inputn(&date,MMDDYY10.));
To actually create the datetime, you need to use PUT:
%let date = 03/15/2013;
%put %sysfunc(putn(%sysfunc(dhms(%sysfunc(inputn(&date,MMDDYY10.)),0,0,0)),datetime26.));
However, the better way to do this if you can is to use a date constant...
%let date=15MAR2013;
%put "&date."d;
Joe is mostly correct. If you want a datetime string of midnight 3/15/13, then use
%let date = 03/15/2013;
%put %sysfunc(putn(%sysfunc(dhms(%sysfunc(inputn(&date,MMDDYY10.)),0,0,0)),datetime26.));
Just using PUTN on a date string to "convert" a date to datetime will convert the number of days from epoch (01JAN1960) to the number of seconds from epoch.
My preference for working with dates in macro variables is to store the actual numeric value in the macro variable, and if I need to view/print the formatted value then assign a format to it on the fly:
%let date = %sysfunc(mdy(3,15,2013));
%put %sysfunc(putn(&date,date9.));
That allows you to use it in comparisons like the below (which I find is the most common task):
data xx;
set something;
where datefield = &date;
run;