I Have a file from excel that is in a short date format, but when SAS reads it in, it turns it into numbers in the 4000 range...when I try and convert this to an excel date with the below formula, it turns the year into 2077...is there a formula to ensure that this date remains in the original format on the read in, or avoid it turning into this 4000 range that is not at all close to the 2017 and 2018 year that my file is starting in. Does that make sense?
data change_date;
format Completed_Date mmddyy8. ;
set check;
completed_date = date_completed;
if 42005 => date_completed >=43466 and date_completed ^=. then
Completed_date = Date_Completed-21916; *commented out 12-21-17 Xalka
dates back to how they are expected;
run;
I am pretty sure this is a duplicate question, but I can't find it.
This is usually caused by mixing character and date values in the same column. This made SAS import the data as a character variable and it results in the actual dates being copied as character versions of the integers that Excel uses to store dates.
Frequently this is caused by entries that look like dates but are really character strings in the Excel file. The best way to fix it is to fix the Excel file so that the column only contains dates. Otherwise you just need to convert the strings to integers and adjust the values to account for the differences in index dates.
So if your values are in a SAS dataset named HAVE in the character variable DATESTRING then you could use this data step to create a new variable with an actual date value.
data want ;
set have ;
if indexc(datestring,'-/') then date=input(datestring,anydtdte32.);
else date = input(datestring,32.) + '01JAN1900'D -2;
format date yymmdd10. ;
run;
The minus 2 is because of difference in whether to start numbering with 1 or 0 and because Excel thinks 1900 was a leap year.
Excel and SAS have different default dates in back-end.
Day 0 in SAS is 1 January 1960 and Day 0 in Excel is 1 January 1900.
So, you will need to convert excel numeric date to sas date using the below formula.
SAS_date = Excel_date - 21916;
data dateExample;
informat dt mmddyy8.;
set dates;
SAS_date = dates - 21916;
dt=sas_Date;
format dt date9.;
run;
Related
I am new to SAS and I am struggling struggling with my code. I would love some help. Am I thinking about this the right way? I have a huge table and I want to extract that data from certain dates. My two dates: 1969-12-01 and 1948-01-01 my sample code:
data null;
call symput ('timenow',put (time(),time.));
call symput ('datenow',put (date(),date9.));
run;
title "The current time is timenow and the date is datenow";
proc print data=sashelp.buy;
run;
So first learn about your dataset. So for example run PROC CONTENTS.
proc contents data=sashelp.buy; run;
Which will show you that there is variable named DATE that has date values (number of days since 1960).
So to reference a specific date use a date literal. That is a quoted string in the style that the DATE informat can read followed by the letter D. You can then use a WHERE statement to filter the data.
data want;
set sashelp.buy;
where date = '31dec1969'd ;
run;
Which will not find any observations since that date does not appear in that dataset.
If you want to select for multiple dates you could either add more conditions using OR.
where (date = '31dec1969'd) or (date = '01jan1948'd);
You can also use the IN operator:
where date in ('31dec1969'd '01jan1948'd);
Note that if your variable contains datetime values (number of seconds) then to pick a specific date you would either need to use a range of datetime literals:
where datetime between '31dec1969:00:00'dt and '31dec1969:11:59:59'dt);
Or convert the number of seconds into number of days and compare to the date literal.
where datepart(datetime) = '31dec1969'd ;
Welcome to StackOverflow Sportsguy3090.
Here I make a dataset called sample with some sample dates. That dataset has a variable called name and another variable called date. Internally, SAS stores dates as the number of days until or after January 1st 1970. That is rough to look at. So I use the format statement to have the dates appear as a 10 character string with month/day/year.
data sample;
name = "Abe "; date = "01Dec1969"d; output;
name = "Betty"; date = "01Jan1948"d; output;
name = "Carl"; date = "06Jun1960"d; output;
name = "Doug"; date = "06Dec1969"d; output;
name = "Ed"; date = "01Jan1947"d; output;
format date mmddyy10.;
run;
The code below subsets the data and puts the good records into a new dataset called keepers. It only keeps the records that are in the date range (including the limit dates).
data keepers;
set sample;
where date between "01jan1948"d and "01Dec1969"d;
run;
I hope that helps.... if not send up another flare.
When I imported my excel sheet some dates imported differently than others. I tried to fix this with the code below to format the date.
DATA volume;
SET mice.volume;
format Date MMDDYY10.;
run;
However, I received the following error.
ERROR 48-59: The format $MMDDYY was not found or could not be loaded.
I had also tried with the following code
DATA volume;
SET mice.volume;
If date= 44138 then date= '11/3';
If date= 44141 then date= '11/6';
run;
NOTE: Character values have been converted to numeric values at the places given by: (Line):(Column).
A Proc Contents shows the variable= Date type= Char Len=7 format=$7 Informat=$7 Label= Date
How do I fix this?
The date column being character having a mix of 'date looking' strings, and Excel date value numbers tells me some of the date values in your Excel are actually strings, such as '11/10 or ='11/10'.
The raw number 44138 is:
a SAS date value is 04-NOV-2080 (obviously not what is wanted)
an Excel date value 03-NOV-2020 (aha!)
03-NOV-2020 as SAS date value is 22222
an offset of -21916 from Excel
-21916 is the SAS date 30-DEC-1899
Date Epochs
An epoch is the date corresponding to a base number 0 in a systems calendar. SAS Base year is 1960 and Excel Base year is 1900.
Formatted
Number Actual Date Date Shown System/Format
------ ----------- ----------- ----------
0 31-DEC-1899 1/0/1900 Excel / Short Date (Formatter is weird at Epoch)
0 01-JAN-1960 01-JAN-1960 SAS / DATE11.
21916 01-JAN-1960 1/1/1960 Excel / Short Date
-21916 30-DEC-1899 31-DEC-1899 SAS / DATE11.
Notice the round trip is from 31-dec-1899 to 30-dec-1899. This due to an Excel 97 bug that has been carried forth for legacy reasons. See Microsoft's explanation in "Excel incorrectly assumes that the year 1900 is a leap year" which pushes the blame back even further to Lotus 1-2-3
The formula to convert between systems S1 and S2 date numbers is to add the # for the other systems epoch date (# # 0)
SAS#(date) = Excel#(date) + SAS#(Excel Epoch Date) - 1 (Excel leap year bug), or
sas_dt = excel_dt + '31-DEC-1899'd - 1; *or;
sas_dt = excel_dt + '30-DEC-1899'd;
What happened
Mixed value types in the Excel date column forced IMPORT to perceive the date variable as character.
The Excel cells with a date looking m/d string were brought in as the string
The Excel cells with a date, likely custom formatted as m/d, were brought in as the underlying Excel date number.
The ERROR
You tried to apply the date format MMDDYY. to the character variable Date.
A character column can not be assigned a numeric or date format, thus you get the
ERROR 48-59: The format $MMDDYY was not found or could not be loaded.
SAS automatically presumed MMDDYY. meant a character format $MMDDYY. because the variable type was character.
The Fix
You can convert the values in the character date column with code such as the following (untested):
if index(date,'/') then
date_fixed = input (trim(date)||'/2020', mmddyy10.);
else
date_fixed = input(date,best12.) + '30-DEC-1899'D;
format date_fixed yymmdd10.;
If you want to continue showing only mm/dd in SAS, use the format NLDATEM5.
format date_fixed NLDATEM5.;
I have a column which has mixed values of month and date (its in character $5 format).
date
7/23
5/23
23MAR
7/19
I want the data to come as uniform date5. format like this
date
23MAR
23MAY
23MAR
19JUL.
Here is the code that I'm using
data DAte_check4again;
set Date_2test;
format check_dt date5.;
check_dt=datepart(date);
run;
SAS stores DATE, TIME and DATETIME values as numbers. The DATEPART() function you are trying to use is for converting DATETIME values to DATE values. But your source variable is character with a length of 5. (FORMATs are just instructions for how to display values).
So your first problem will be to convert the string into a DATE value. You can then take the first 5 characters of the DATE. format and store that into either your original variable or some other variable. Assuming that the month/day values are for the current year and you only have those two styles of strings here is one method to generate a date and also the 5 character string.
data want;
set have ;
if index(date,'/') then date_ck = input(cats(date,'/',year(today())),mmmddyy10.);
else date_ck = input(cats(date,year(today())),date9.);
format date_ck date9.;
new_date = substr(put(date_ck,date9.),1,5);
run;
I need to change what it is currently at into the date9 format.
input Company_Name$ 1-58 Form_Type$ 59-70 CIK Date_filed$ 86-96 File_Name$ 118-141;
length Date_filed $10.;
format Date_filed yymmdd10.;
ndate=put(Date_filed, yymmdd10.);
this is what I have, but it doesn't work. I am not sure how to do this.
SAS stores dates in numeric variables as the number of days since 1960. Once you have a valid date value you can attach any of the many formats that change how the value is displayed. To read directly from the source file into a date value using an INFORMAT that is appropriate for the value. Note that you cannot combine an informat with the column range in the input statement. Instead you can use # to position at the first column of the date string and then use formatted input. Also you did not tell INPUT what columns to read for the variable CIK.
input Company_Name $ 1-58 Form_Type $ 59-70
CIK 71-85 #86 Date_filed yymmdd10.
File_Name $ 118-141
;
format Date_filed date9.;
Note you were reading 11 columns before but date strings in YYYY-MM-DD style only need 10 columns, so check if your date strings are in columns 86-95 or columns 87-96. If you don't read the right columns you might miss the second digit of the day of the month or the first digit of the year.
I have a column that contains date values. So when imported as numeric, it shows 20668, 20669...etc. if I format it as yymmddn8, it shows 20160802 etc. However, what I really want is a numeric variable that shows 20160802. I have tried to create other to get day, month, year and then concatenate them. Unfortunately, the issue is if month and day is 1 digit, it would only show 201682. what would be the quickest way to achieve my goal. I guess a can turn the day and month variable to text and add 0 if day or month is less than 10. But this is not elegant and efficient. Please help.
Thanks
You can just wrap an input around that format:
data test;
date = 20668;
full_date = input(put(date,yymmddn8.),best12.);
run;
The put is converting the date to character in the format as you want it to appear, and the input with the best12. format is converting it back to numeric in that format.
It sounds like you just need to attach a format to your variable.
format date yymmddn8. ;
Try running this program to see a few of the different formats that are available for displaying dates.
data _null_;
do date = 20668, 20669 ;
put (6*date) (=10. =date9. =yymmddn8. =mmddyy10. =ddmmyy10. =yymmdd10.) ;
end;
run;