convert timestamp into SAS macro variable - sas

how to convert the timestamp into numeric value without microseconds value getting rounded up and store it in a macro variable
data temp;
ts='2022-05-18:10:11:12.796429';
ts1 = input(ts,anydtdtm26.);
putlog 'ts1-->' ts1;
call symput('new_ts1',ts1);
run;
%put new_ts1: &new_ts1;
ts1-->1968487872.8
new_ts1: 1968487872.8
Is it possible to store the actual value instead of the round value?

You keep asking this same question.
Correction
NO. It is impossible to store datetime (aka timestamp) values to the micro second in SAS. The values will exceed the limits of precision for storing decimal values with fractions as floating point numbers.
You can store that large a number as an integer number of microseconds. But not as a number of seconds with microseconds represented as fractions of a second.
Example:
836 data test;
837 second = '18MAY2022:10:11:12'dt + 0.796429;
838 micros = '18MAY2022:10:11:12'dt*1E6 + 796429;
839 put second= comma30.6 / micros = comma30. ;
840 run;
second=1,968,487,872.796420
micros=1,968,487,872,796,429
Notice how the microseconds place digit is lost when stored in number of seconds but when stored as an integer count of microseconds instead the value is still there.
NO. You cannot use the ANYDTDTM informat to convert that specific string into a datetime value with microsecond precision. Use a different method. And store the microseconds in a separate variable from the datetime.
date test;
ts='2022-05-18:10:11:12.796429';
dt=dhms(input(ts,yymmdd10.),0,0,input(substr(ts,12),time8.));
microseconds = input(scan(ts,-1,'.'),6.);
format dt datetime19. microseconds z6. ;
run;
NO. You cannot use implicit passthru to DB2 to move datetime values and retain the precision to the micro second.
To move the values from DB2 to SAS convert them to a string in DB2 and move the string. You can then use a method like above to convert into an actual datetime value if you need.
To move the values back to DB2 you reverse the process and move the value as a string and use DB2 code to convert it to a DB2 timestamp value. Or generate code to run in DB2 via explicit pass thru (perhaps by building the text of a DB2 timestamp literal into a macro variable) that will transfer the value.
So perhaps something like:
%let myts=%put<what ever the heck syntax works for timestamp value in DB2>;
proc sql;
connect to db2 ... ;
execute by db2
(insert into myschema.mytable (myts)
values ( &myts. )
)
;
You could try to build such a string be concatenating the date, time and microsecond pieces. Make sure the use the Z format when converting the microseconds into a string so that values less than a tenth of a second will have the needed leading zeros.
So if you want to generate a string like '2022-05-18:10:11:12.796429' you might do this:
data _null_;
set test;
call symputx('myts',cats(
"'",put(datepart(dt),yymmddd10.)
,":',put(dt,tod8.)
,".",put(milliseconds,z6.)
,"'"));
run;

Related

Convert numeric variable in Time variable in

I imported a CSV file in SAS and it has a time variable.But the time variable is in numeric format like 515 which refers 05:15 , 1110 refers 11:10 and 2030 which refers 20:30.
I need to convert it into proper time format and then take out the Hour from it.I have tried:
new_time=put(time,hhmm.);
The output which i got is like 0:09 , 0:10.
Please help me out.
Try this:
data have;
input mytimevar;
cards;
515
1110
2030
;
run;
data want;
set have;
time = input(put(mytimevar, 4.) || '00', hhmmss.);
format time tod5.;
run;
How this works:
Convert timevar to text using put
Append 00 for seconds
Input as time variable using hhmmss. informat
Display with leading zeros for hours using tod5. format
A Time value in SAS is numeric whose value is the number of seconds. The display of such a value typically involves associating a time format such as TIMEw.d, HHMMw.d, MMSSw.d. There are many more.
From SAS Help (my italics)
SAS time value
is a value representing the number of seconds since
midnight of the current day. SAS time values are between 0 and 86400.
NOTE: The time formats will handle time values (number of seconds) outside the 0 to 24 hours range.
For your case of a time value (call it the csvtime) encoded as 100*hours + minutes the SAS time value can be computed using the dhms function specifying zero for the d and s arguments, and the h and m arguments parsed from the csv time using integer division and modulus arithmetic.
sastime = dhms (0, floor(cvstime/100), mod(cvstime,100), 0);
format sastime time7.; * values displayed will be rendered using hh:mm:ss construct;

Convert a time/character variable into numeric in SAS

I am using the following code:
data time2;
set time;
varnew = put(varold, best12.) ;
run;
The original variable measures duration, so the values are in seconds, and displayed like 0:03 etc. and I want to convert it into 0.03
There is a new column generated for varnew, however, no values are displayed. What could be the reason?

Read time value in SAS of the form 515 as 5:15

i have variable with time values like 515 which should be read like 5:15
To do this I used the following code-
data flights;
set cs.flights;
format sched_dep_time hhmm. dep_time hhmm. ;
run;
but i get result for 515 as 0.09
which I think is the time it is calculating from 12:00 am in seconds .
I also use time. format but no use.
how do i deal with this?
A format only changes the way a value is displayed. In this case we need to change the actual value, such that it represents the number of seconds since midnight.
The following approach serves (along with the time_diff as requested):
data flights;
sched_dep_time=515;
dep_time=1215;
format sched_dep_time dep_time time_diff hhmm. ;
sched_dep_time=hms(round(sched_dep_time,100)/100
,mod(sched_dep_time,100),0);
dep_time=hms(round(dep_time,100)/100
,mod(dep_time,100),0);
time_diff=sched_dep_time-dep_time;
put (_all_)(=);
run;
gives:
sched_dep_time=5:15 dep_time=12:15 time_diff=-7:00
As you suggested, SAS stores time values as number of seconds since midnight. So the value 515 is 515 seconds after midnight. To get the value that represents 05:15 you need to do some conversions.
SAS has an INPUT function which is used to read character data, and you can specify the format of the data. This allows use to read the character value '0515' and convert it to the numeric 18900 which represents the time 05:15.
Below uses the PUT function to convert the numeric value 515 to the character value '515', and the INPUT function to covert that to 18900. The time format makes 18900 print as 05:15:00.
data have;
sched_dep_time=515;
dep_time=1515;
run;
data want;
set have;
SchedDepTime=input(put(sched_dep_time,4.),hhmmss.);
DepTime=input(put(dep_time,4.),hhmmss.);
format SchedDepTime DepTime time.;
put (Sched_Dep_Time SchedDepTime Dep_Time DepTime)(=);
run;
returns:
sched_dep_time=515 SchedDepTime=5:15:00 dep_time=1515 DepTime=15:15:00

How to convert Datetime into SAS format

I am working with a huge number of observations in different tables in different versions.
I will use a date %let date_to_view = "20JAN2014:16:10"dt;
But how to convert this date into SAS format?
I knew how to Convert SAS data type (use proc sql):
dhms("01JAN1970'd,3,0,i.valid_dttm/1000) format datetime20.
I see date 20JAN2014:16:34:10 is 1390224849927 but how to convert it into code?
In your formula dhms("01JAN1970'd,3,0,i.valid_dttm/1000) you are converting a number that represents the number of milliseconds since 01JAN1970 to a SAS datetime value that represents the number of seconds since 01JAN1960. You also appear to be adding 3 hours.
So it sounds like your question is how to convert a SAS DATETIME value into a Unix timestamp value. So just reverse the arithmetic.
Your formula to convert from a Unix timestamp to a SAS datetime was:
sasdt2 = '01JAN1970:00:00'dt + '03:00't + unix_timestamp2/1000 ;
So to convert from a SAS datetime value to a Unix timestamp use:
unix_timestamp1 = 1000*(sasdt1 - '01JAN1970:00:00'dt - '03:00't) ;
"20JAN2014:16:10"dt is already in the correct SAS date (datetime) format, but as a date literal. SAS stores this as a number, representing the number of seconds since 01JAN1960:00:00:00.
If you just want the date component of the datetime, use the datepart() function, and format the result accordingly, e.g. date9..
data want ;
dt = "20JAN2014:16:10"dt ;
date = datepart(dt) ;
format dt datetime19. date date9. ;
/* To have 'date' show as the unformatted value, simply remove the format */
format date best32. ;
run ;

SAS date or numeric data?

%let months_back = %sysget(months_back);
data;
m = intnx('month', "&sysdate9"d, -&months_back - 2, 'begin');
m = intnx('day', put(m, date9.), 26, 'same');
m2back = put(m, yymmddd10.);
put m2back;
run;
NOTE: Character values have been converted to numeric values at the
places given by: (Line):(Column).
5:19 NOTE: Invalid numeric data, '01OCT2012' , at line 5 column 19.
I really don't know why this go wrong. The date string is numeric data?
PUT(m, date9.) is the culprit here. The 2nd argument of INTNX needs to be numeric (i.e. a date), the PUT function always returns a character value, in this instance '01OCT2012'. Just take out the PUT function completely and the code should work.
m = intnx('day', m, 26, 'same');
SAS stores dates as numbers - and in fact does not have a truly separate type for them. A SAS date is the number of days since 1/1/1960, so a bit over 19000 for today. The date format is entirely irrelevant to any date calculations - it is solely for human readibility.
The bit where you say:
"&sysdate9"d
actually converts the string "01JAN2012" to a numeric value (18304).
There's actually a quicker way to accomplish what you're trying to do. Because days correspond to whole numbers in SAS, to increment by one day you can simply add one to the value.
For example:
%let months_back=5;
data _null_;
m = intnx('month', today(), -&months_back - 2, 'begin');
m2 = intnx('day', m, 26, 'same');
m3 = intnx('month',"&sysdate9"d, -&months_back - 2)+26;
m2back = put(m2, yymmdd10.);
put m= date9. m2= yymmdd10. m3= yymmdd10.;
run;
M3 does your entire calculation in one step, by using the MONTH interval, then adding 26. INTNX('day'...) is basically pointless, unless there's some other value to using the function (using a shift index for example).
You also can see the use of a format in the PUT(log) statement here - you don't have to PUT it to a character value and then put that to the log to get the formatted value, just put (var) (format.); - and string together as many as you want that way.
Also, "&sysdate9."d is not the best way to get the current date. &sysdate. is only defined on startup of SAS, so if your session ran for 3 days you would not be on the current day (though perhaps that's desired?). Instead, the TODAY() function gets the current date, up to date no matter how long your SAS session has been running.
Finally - I recommend data _null_; if you don't want a dataset (and naming the result dataset if you do want it). data _null_ does not create a dataset. data; simply creates increasing numbers of datasets (data1, data2, ...) which quickly fill up your workspace and make it hard to tell what you're doing.