Convert to a SAS Time - sas

I have a txt file containing time in this format 161058.262 which is intended to be 16:10:58.262.
I cannot find an INFORMAT that will turn this value into the correct SAS numeric time value. TIME12.3 will convert into a numeric. It gets stored as 579824520 and displays using format TOD12.3 format as 22:22:00.000
Any suggestions?
Thanks
Dan

I would do a quick transformation to make an existing informat work. For example, your format is the same as what B8601TM expects, except for the dot that separates the fraction of a second. You can strip out the dot from your string and then apply the informat.
Example:
data test;
input t $10.;
format tt TOD12.3;
tt = inputn(compress(t, , "kn"), "B8601TM9.3");
datalines;
161058.262
; run;

I don't know about a specific informat, but you certainly can work in colons, or do the math to make it into a time using HMS.
data test;
informat t_pre $10.;
input t_pre $;
t = input(catx(':',substr(t_pre,1,2),substr(t_pre,3,2),substr(t_pre,5)),TIME12.3);
*CATX concatenates using a delimiter, so this generates a string like 16:10:58.262;
*Then converts to TIME12.3;
put t= TIME12.3 t_pre=;
datalines;
161058.262
;;;;
run;
data test;
input t_pre;
t = hms(floor(t_pre/10000),floor(mod(t_pre,10000)/100),mod(t_pre,100));
*HMS generates a time value from hours, minutes, seconds, and allows milliseconds in the seconds;
*So we use combination of division and modulo to separate the number into component parts;
put t= TIME12.3;
datalines;
161058.262
;;;;
run;

code
data _null_;
input int_val $10.;
format time_val timeampm15.3;
time_val = input(
prxchange('s/(\d?\d)(\d\d)(\d\d\.\d\d\d)/$1:$2:$3/',
-1, int_val),
time10.3);
put int_val
#15 time_val timeampm15.3
#30 time_val 10.3;
datalines;
000000.001
012345.678
12345.678
161058.262
235959.999
run;
log
000000.001 12:00:00.000 AM 0.000
012345.678 1:23:45.600 AM 5025.600
12345.678 1:23:45.670 AM 5025.670
161058.262 4:10:58.200 PM 58258.200
235959.999 11:59:59.900 PM 86399.900
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds

Related

SAS increment macro variable yyyymm by 1 month

Basically i'm trying to get the below month4 but in a macro format.
Been a while since i've done macro functions so this is a bit tricky.
data test;
input month $8.;
datalines ;
202210
202211
202201
202210
;
run;
data test2;
set test;
format month2 date9. month3 date9.;
test = cats(month,"01");
month2 = input(cats(month, "01"), yymmdd8.);
month3 = intnx("month",input(cats(month, "01"), yymmdd8.),-1);
month4=trim(substr(put(month3,yymmddn8.),1,6));
run;
I suspect this is what you are looking for, but your request is not very clear.
%let month=202212;
%let month4=%sysfunc(intnx(month,%sysfunc(inputn(&month,yymmn6)),1),yymmn6);
It uses the INPUTN() function to convert your YYYYMM string by reading it with the YYMMN6. informat. It then uses the INTNX() function to move to the beginning of the next month and returns the result formatted with YYMMN format so you get back another YYYYMM string of digits.

how to get flag and dateformates in sas

Hi I have one doubt in sas
in dataset date format have 08-04-1988
base on this values I want create date styles and along flag values
For datetime flag creation if dateandtime have then consider flag 1 else 0
for date if date have then consider flag 1 else 0
for time if time have then consider flag 1 else 0
DATA DAT;
X= "08APR1988"D;
FORMAT X DDMMYYD10.;
RUN;
Based on above value I want output like below
Datetime | Date | Time | DatetimeFlag | DateFlag |TimeFlag
08APR1988 00:00:00 |08-04-1988 |00:00:00 | 0 |1 |0
I tried like below
DATA DUMM;
SET DAT;
DT=PUT( X, DDMMYY10.);
DATEF=PUT( X, date9.);
DTs=PUT( X, DATETIME32.);
TimeF=PUT( X, TIME.);
RUN;
here if donot have time then its takeing default datewith time similar time also
i want display if time is not available then consider 00:00:00 similar if date not available the date aslo : 1960-01-01
but above scirpt is not given expeted result ,
can you please tell me how to wirte sas coding to achive this task.
SAS has two value types, numeric and character.
Date and DateTime values are numeric with handling.
Date values are the number of days since 01JAN1960.
DateTime values are the number of seconds since 01JAN1960.
Non-integer date values do not get special interpretation (in other date systems, such as Excel, the decimal part of a numeric is the fraction of the day as well)
Non-integer DateTime values are fractional seconds.
You can convert the date to datetime by multiplying by the number of seconds in a day (86,400)
Suppose you had a non-integer date value, such as
data _null_;
D = '01JAN2019'D + 0.5;
format D yymmdd10.;
put D= / D=best12.;
DT = D * 86400;
format DT datetime21.2;
put DT= / DT=best12.;
run;
---------- LOG ----------
D=2019-01-01
D=21550.5
DT=01JAN2019:12:00:00.00
DT=1861963200
You can separate out the date and time parts of a datetime value using the functions DATEPART and TIMEPART
data have;
dt = '01FEB2019:12:34:56.78'DT; output;
dt = '15FEB2019:00:00:00'DT; output;
format dt datetime21.2;
run;
data want;
set have;
d = datepart (dt);
t = timepart (dt);
format d yymmdd10.;
format t time12.2;
dt_is_just_date = (t eq 0);
dt_has_time_part = (t ne 0);
run;
proc print data=want;
run;
-------
dt_is_ dt_has_
just_ time_
Obs dt d t date part
1 01FEB2019:12:34:56.78 2019-02-01 12:34:56.78 0 1
2 15FEB2019:00:00:00.00 2019-02-15 0:00:00.00 1 0

SAS group by first digits

I have a variable in SAS with a lot of numbers, for example 11000, 30129, 11111, 30999. I want to group this by the first two digits so "11000 and 11111" and "30129 and 30999" will be in a own table.
It's quite simple,
You have to create a second column and extract the 2 first digit.
Then sort the dataset by this second columns.
data test;
infile datalines dsd ;
input a : 15. ;
datalines;
11000,
30129,
11111,
309999,
;
run;
data test_a;
length val_a $2;
set test;
val_a= SUBSTRN(a,1,2);
run;
proc sort data=test_a out=test_b;
by val_a;
run;
Result will be :
val_a a
11 11000
11 11111
30 30129
30 309999
And then you can create 2 dataset with selection on the val_a like this :
data want data_11 data_30;
set test_b;
if val_a = 11 then output data_11;
if val_a = 30 then output data_30;
run;
Regards,
I think I did like you, but my new column only shows with ".". But I think your answer can give me some help anyways, thank you!
data books;
infile "&path\Boken.csv" dlm=';' missover dsd firstobs=2;
input ISBN: $12.
Book: $quote150.;
run;
data test_a;
format val_ISBN 15.;
set books;
val_ISBN= SUBSTRN(ISBN,1,2);
run;
proc sort data=test_a out=test_b;
by val_ISBN;
run;
proc print data=test_b (obs=10) noobs ;
run;

Convert mm/dd/yy to MonthName DayNumber, YearNumber in SAS

I want to be able to convert an entire column of dates this way. For example, 01/01/2017 to January 1, 2017. I realize there is a convoluted way of doing this but I am not entirely sure how i'd approach that logically. Also, does there happen to be a SAS format that does this? Thanks.
There does happen to be a format you can use. Here is a worked example using test data:
data test;
input datestring $;
datalines;
01/01/2017
;
run;
Using input converts the string value into a SAS date, and then the put function is used to create a character variable holding the representation you are looking for:
data test2;
set test;
date_as_date = input(datestring,ddmmyy10.);
date_formatted = put(date_as_date,worddate20.);
run;
The number 20 is used to describe a length that is long enough to hold the full value, using a lower number may result in truncation, e.g.
date_formatted = put(date_as_date,worddate3.);
put date_formatted=;
dateformatted=Jan
In some cases, the desired date format may NOT exist (in this case, it does 'worddate20.'), but as an example...
You could either write a function-style macro to convert a SAS date to "monname + day, year" format, e.g.
%MACRO FULLMDY(DT) ;
catx(', ',catx(' ',put(&DT,monname.),put(&DT,day.)),put(&DT,year4.))
%MEND ;
data example1 ;
dt = '26jul2017'd ;
fulldate = %FULLMDY(dt) ;
run ;
Or, you could build a custom format, covering all the dates which may exist in your data, e.g.
data alldates ;
retain fmtname 'FULLMDY' type 'N' ;
do dt = '01jan1900'd to '01jan2100'd ;
mdy = catx(', ',catx(' ',put(dt,monname.),put(dt,day.)),put(dt,year4.)) ;
output ;
end ;
rename dt = start
mdy = label ;
run ;
proc format cntlin=alldates ; run ;
data example2 ;
dt = '26jul2017'd ;
format dt fullmdy. ;
run ;

SAS: using first. and last. to process a date range

I am trying to go through a list of dates and keep only the date range for dates that 5 or more occurrences and delete all others. The example I have is:
data test;
input dt dt2;
format dt dt2 date9.;
datalines;
20000 20001
20000 20002
20000 20003
21000 21001
21000 21002
21000 21003
21000 21004
21000 21005
;
run;
proc sort data = test;
by dt dt2;
run;
data check;
set test;
by dt dt2;
format dt dt2 date9.;
if last.dt = first.dt then
if abs(last.dt2 - first.dt) < 5 then delete;
run;
What I want returned is just one entry, if possible, but I would be happy with the entire appropriate range as well.
The one entry would be a table that has:
start_dt end_dt
21000 21005
The appropriate range is:
21000 21001
21000 21002
21000 21003
21000 21004
21000 21005
My code doesn't work as desired, and I am not sure what changes I need to make.
last.dt2 and first.dt are flags and can have value in (0,1), so condition abs(last.dt2 - first.dt) < 5 is always true.
Use counter variable to count records in group instead:
data check(drop= count);
length count 8;
count=0;
do until(last.dt);
set test;
by dt dt2;
format dt dt2 date9.;
count = count+1;
if last.dt and count>=5 then output;
end;
run;
I'm not sure why you are looking to use the last.dt2 and the first.dt within your delete function so I have turned it around to create your desired output:
data check2;
set test;
by dt ;
format dt dt2 date9.;
if last.dt then do;
if abs(dt2 - dt) >= 5 then output;
end;
run;
Of course, this will only work if your file is sorted on dt and dt2.
Hope this helps.