Reading Time Data using INFILE option - sas

I have a .csv file which has some flight information. Sample data is shown below.
date|sched_dep_time|dep_time|sched_arr_time|arr_time
1/1/2013|515|517|819|830
The 515 here actually means 5:15Hrs. How can I read this data into SAS correctly? If I use the time. format, it is coming up with some strange timings. I have seen some code snippets, which has to be written exclusively to do these time conversions. But is there are more straight forward method available?

Use the informat HHMMSS, which will read it in correctly.
data have;
informat date ddmmyy10. sched_dep_time dep_time sched_arr_time arr_time hhmmss.;
format sched_dep_time dep_time sched_arr_time arr_time time.;
input date sched_dep_time dep_time sched_arr_time arr_time;
cards;
1/1/2013 515 517 819 830
;
run;
proc print data=have;run;

I didn't realize the HHMMSS. INFORMAT would work. Reeza's answer is best. If you want a custom function, here you go.
options cmplib=work.fns;
proc fcmp outlib=work.fns.time;
function to_time(x);
minutes = mod(x,100);
hour = (x-minutes)/100;
time = hms(hour,minutes,0);
return (time);
endsub;
run;
data test;
format in_val best.
out_time time.;
in_val = 512;
out_time = to_time(in_val);
put in_val out_time;
run;

Related

How to convert string to date in SAS?

I have a table in SAS where in one column, the date is stored (e.g. "2005/10").
How do I have to convert this to a SAS data format?
Among many other tries, I tried this code:
data test;
format date YYMMS.;
date = input(ObservationMonth, YYMMS.);
put date=date9.;
run;
You could just use the anydtdte. informat.
data want;
format date yymms.;
text="2005/10";
date=input(text,anydtdte.);
put date;
run;
This informat detects most date formattings and converts the character-stored value to a SAS date.
One way is to use substr() and mdy() to extract the date components:
data _null_;
ObservationMonth ="2005/10";
date =mdy(substr(ObservationMonth,6,2),1,substr(ObservationMonth,1,4));
put date = date9.;
run;
Another option is to use the anydtdte informat (note that results may differ depending on your locale):
data _null_;
ObservationMonth ="2005/10";
date =input(ObservationMonth,anydtdte.);
put date = date9.;
run;
Yet another option is to modify the input to enable use of the YYMMDDw. informat:
data _null_;
ObservationMonth ="2005/10";
date =input(ObservationMonth!!'/01', YYMMDD10.);
put date = date9.;
run;
you're fantastic, guys! Thank you so much, with a "set" statement it works fine!

Reading in Data into SAS using 'Where' function

For some reason I'm not being able to read in the data properly. I want to be able to read in a large data set but within only specific dates such as Jan 2004 to FEB 2004. My Code is the following:
DATA Work.sales_fact;
SET Work.sales_fact_subset;
WHERE '01JAN2004'd <= Order_Date <= '14FEB2004'd;
RUN;
PROC PRINT;
RUN;
What am I doing incorrectly?
I think you have DATA and SET switched. DATA is what you want to create. SET is where the data is coming from.
DATA Work.sales_fact_subset ;
SET Work.sales_fact;
WHERE '01JAN2004'd <= Order_Date <= '14FEB2004'd;
RUN;
PROC PRINT data=Work.sales_fact_subset;
RUN;
Here is an example of this working..
Please check your dataset.
data want;
set sashelp.rent;
where "01feb1999"d <= date <= "02feb2003"d;
run;
If your table names and date structure is correct, your query is correct. Here is a sample of what I did with the correct result set.
data inputs;
input Date1 date9. ;
Format date1 date9.;
cards;
01JAN2004
02FEB2004
03MAR2004
04JUN2004
05JUL2004
;
DATA inputss;
SET inputs;
WHERE '01JAN2004'd <= Date1 <= '14FEB2004'd;
RUN;
PROC PRINT;
RUN;

SAS Date Informat with Milliseconds

I am trying to create a SAS informat for the following date format:
"yyyy-mm-dd hh:ii:ss.SSS UTC", example: "2016-01-14 10:31:01.456 UTC"
I've gotten close using the following format code:
PROC FORMAT;
PICTURE MyDate other='%0Y-%0m-%0d %0H:%0M:%0s UTC' (datatype=datetime);
RUN;
Unfortunately when I try and use this as an INFORMAT I get an error "can't find format MyDate", as it hasn't been defined as an informat, just an output format.
I can try and create an informat from a dataset created from this format, but due to the milliseconds constraint it will only create values that map to times with .000 in the milliseconds section. For example:
DATA MyInDate ;
RETAIN FMTNAME "MyInputDate" type "I" ;
do label = "1jan2016:00:00:00"dt to
"2feb2016:00:00:00"dt by 1;
start = trim(left(put(label,MyDate.)));
output ;
end ;
RUN;
PROC FORMAT CNTLIN=MyInDate;
RUN;
Even if I were able to enumerate a dataset with milliseconds it would be prohibitively large. Since my dates can span years.
Is it possible to truncate my input data BEFORE passing it to the informat? I don't care about the milliseconds or the UTC qualifier. I can't change the input data.
EDIT: Using anydtdtm. as an informat results in empty values without error messages. Here is the data step making use of this informat:
DATA WORK.ImportDatTest;
LENGTH
'Event Time'n 8
;
FORMAT
'Event Time'n DATETIME25.
;
INFORMAT
'Event Time'n anydtdtm.
;
INFILE DATALINES DLM=','
;
INPUT
'Event Time'n : ANYDTDTM.
;
DATALINES;
2016-01-11 17:23:34.834 UTC
2016-01-11 17:23:34.834 UTC
2016-01-11 17:23:34.834 UTC
;
RUN;
Unfortunately, there is no way to create a picture informat in SAS currently. You would need to convert your data to a format SAS has a built-in informat for, or use a function or similar to format the data.
However, yours already is in such a format, so you shouldn't need to create an informat.
data test;
x="2015-10-05 10:12:24.333 UTC";
y=input(x,anydtdtm.);
put y= datetime17.;
run;
You can certainly truncate data while using an informat; by specifying a length in the informat, it will truncate to that length.
Here's an example using input from datalines:
data test;
infile datalines dlm=',' dsd;
input y :anydtdtm32.;
put y= datetime22.3;
datalines;
2015-10-05 10:12:24.333 UTC
2014-03-01 08:08:05.435 UTC
2013-01-01 23:02:05.445 UTC
;;;
run;

How to calculate 'age last birthday' on a given date for a given birthday in SAS PROC SQL step

I want to calculate 'age last birthday' on a specific evaluation date, given a specific date of birth, using a SAS PROC SQL command.
How can I do this and are there any limitations?
Sample Input
DATA INPUTS;
infile cards dlm=',' dsd;
INPUT DOBDt :DATE9. EvalDt :DATE9. expected;
FORMAT DOBDt date9. EvalDt date9.;
CARDS;
11MAY2009,10MAY2015,5
11MAY2009,11MAY2015,6
11MAY2009,12MAY2015,6
28FEB1984,01DEC2015,31
29FEB1984,28FEB2012,27
29FEB1984,29FEB2012,28
29FEB1984,01MAR2012,28
;
RUN;
The goal would be to take the dobDt as an input, evaluate on the EvalDt and produce the answer of expected
This can be done as such :
PROC SQL
PROC SQL;
CREATE TABLE outputs2 AS
select
*
,intck('year',DOBDt,EvalDt,'c') AS actual
,((calculated actual) eq expected) AS check
FROM
inputs
;
QUIT;
actual, the calculated value, matches expected, the desired outcome, for all the examples provided. I am not aware of any limitations to this approach although there are probably some extreme ages that it cannot calculate due to SAS dates having a limited range of values.
As a bonus:
DATA STEP
DATA outputs;
set inputs;
actual = intck('year',DOBDt,EvalDt,'c');
check = (actual eq expected);
RUN;
This is how we used to do it back in the day. Also "age at last birthday" seems pretty clear to me.
DATA INPUTS;
infile cards dlm=',' dsd;
INPUT DOBDt :DATE9. EvalDt :DATE9. expected;
FORMAT DOBDt date9. EvalDt date9.;
age = year(evaldt)-year(dobdt) - (month(evaldt) eq month(dobdt) and day(evaldt) lt day(dobdt)) - (month(evaldt) lt month(dobdt));
CARDS;
11MAY2009,10MAY2015,5
11MAY2009,11MAY2015,6
11MAY2009,12MAY2015,6
28FEB1984,01DEC2015,31
29FEB1984,28FEB2012,27
29FEB1984,29FEB2012,28
29FEB1984,01MAR2012,28
;;;;
RUN;
proc print;
run;

Character date 31.03.2001 to numerical, SAS

I have a variable that was entered as 31.01.2002 for all entries, and is a character. I would like to put it in numerical form with date9. .
I have tried the below:
date=input(oldway, 10.);
date=input(oldway, date9.);
put date=ddmmyy10.;
date=input(compress(oldway,'.'),10.);
date = INPUT(compress(oldway),date9.);
format date date9.;
run;
I have also tried combinations of the above and to no avail.
Any ideas for forward motion?
Kind Regards!!
You can't input your date using the date9. informat as your string variable isn't in that format. You can use ddmmyy10., though, and that also takes care of the . characters.
data have;
input old $10.;
cards;
31.01.2014
28.02.2014
01.01.2015
;
run;
data want;
set have;
new = input(old, ddmmyy10.);
format new date9.;
run;
try this:
data _null_;
date ="31.01.2014";
date=compress(date,".");
new_date=input(date,ddmmyy8.);
format new_date date9.;
put new_date;
run;