Adding seconds to time variable - sas

*data final;
set final;
duration = redate-ondate;
dudays = floor(duration/86400);
duhrs = floor((duration-(dudays*86400))/3600);
dumins = floor((duration-(dudays*86400+duhrs*3600))/60);
****************Set up new variable duration**************;
attrib dur length=$11.;
if ae_term ne 'None' and dudays ne . then
dur = left(put(dudays,z2.))||':'||left(put(duhrs,z2.))||':'||left(put(dumins,z2.));
else dur = '';
run;*
I have this code but need to calculate seconds and concatenate to dur as I have an adverse event that is less than a minute so won't display. What's the most efficient way to do this?

You can calculate the remaining seconds and then append to your time string like this:
dusec = duration-(dudays*86400+duhrs*3600+dumins*60);
if ae_term ne 'None' and dudays ne . then
dur = left(put(dudays,z2.))||':'||left(put(duhrs,z2.))||':'||left(put(dumins,z2.)||':'||left(put(dusec,z2.)));
One note - using put(dudays,z2.) assumes your duration is never more than 99 days.

Ok, this should simplify things somewhat:
dudays = FLOOR(duration/86400);
duhrs = FLOOR(MOD(duration,86400)/3600);
dumins = FLOOR(MOD(duration,3600)/60);
dusec = MOD(duration,60);

The difference between two datetime values is a number of seconds (so it is also a datetime value). You can use the DATEPART() and TIMEPART() function to divide into the number of days and seconds since midnight. The TOD11.2 format will display seconds in HH:MM:SS.mm style.
length dur $20;
if n(redate,ondate)=2 and ae_term not in (' ','None') then do;
duration = redate-ondate;
dur = catx(':',datepart(duration),put(timepart(duration),tod11.2));
end;

Related

Postgresql - Looping based on timestamp

i am working on a scenario where need to run a particular code block for 5 mins.
I tried various options but no luck till now.
Could you please guide me.
Attaching the half-baked block:
DO
$do$
DECLARE
i int;
startTime TIMESTAMP;
endTime TIMESTAMP;
BEGIN
i := 1;
startTime := now();
endTime := now() + (1 * interval '5 minute');
RAISE NOTICE 'City Name:(%)(%)',statement_timestamp(),now() + (1 * interval '5 minute');
WHILE statement_timestamp() < endTime LOOP
RAISE NOTICE 'City Name:(%)(%)(%)',endTime,now(), statement_timestamp();
-- example:
--create table if not exists test12345(id int,start_dt TIMESTAMP,end_dt TIMESTAMP);
insert into test12345
select i,startTime,endTime;
--RAISE NOTICE startTime;
RAISE NOTICE 'City Name:(%)', statement_timestamp();
--startTime := statement_timestamp();
END LOOP;
END;
$do$;
thanks in advance.

Calculating value weighted returns in SAS

I have some data in the following format:
COMPNAME DATA CAP RETURN
I have found some code that will construct and calculate the value-weighted return based on the data.
This works great and is below:
PROC SUMMARY NWAY DATA = Data1 ; CLASS DATE ;
VAR RETURN / WEIGHT = CAP ;
OUTPUT
OUT = MKTRET
MEAN (RETURN) = MONTHLYRETURN
RUN;
The extension that I would like to make is in my head a little bit complicated.
I want to make the weights based on the market capitalization in June.
So this will be a buy and hold portfolios. The actual data has 100's of companies but to give a representative example for two companies with the sole explanation of how the weights will evolve...
Say for example I have two companies, A and B.
The CAP of A is £100m and B is £100m.
In July of one year, I would invest 50% in A and 50% in B.
The returns in July are 10% and -10%.
Therefore I would invest 55% and 45%.
It will go on like this until next June when I will re-balance again based on the market capitalisation...
10% monthly return is pretty speculative!
When the two companies differ by more than 200 you will need to also sell and buy to equalize the companies.
Presume the rates per month are simulated and stored in a data set. You can generate a simulated ledger as follows
add returns
compare balances
equalize by splitting 200 investment if balances are close enough
equalize by investing all 200 in one and selling and buying
Of course, a portfolio with more than 2 companies becomes a more complicated balancing act to achieve mathematical balance.
data simurate(label="Future expectation is not an indicator of past performance :)");
do month = 1 to 60;
do company = 1 to 2;
return = round (sin(company+month/4) / 12, 0.001); %* random return rate for month;
output;
end;
end;
run;
data want;
if 0 then set simurate;
declare hash lookup (dataset:'simurate');
lookup.defineKey ('company', 'month');
lookup.defineData('return');
lookup.defineDone();
month = 0;
bal1 = 0; bal2 = 0;
output;
do month = 1 to 60;
lookup.find(key:1, key:month); rate1 = return;
ret1 = round(bal1 * rate1, 0.0001);
lookup.find(key:2, key:month); rate2 = return;
ret2 = round(bal1 * rate2, 0.0001);
bal1 + ret1;
bal2 + ret2;
goal = mean(bal1,bal2) + 100;
sel1 = 0; buy1 = 0;
sel2 = 0; buy2 = 0;
if abs(bal1-bal2) <= 200 then do;
* difference between balances after returns is < 200;
* balances can be equalized simple investment split;
inv1 = goal - bal1;
inv2 = goal - bal2;
end;
else if bal1 < bal2 then do;
* sell bal2 as needed to equalize;
inv1 = 200;
inv2 = 0;
buy1 = goal - 200 - bal1;
sel2 = bal2 - goal;
end;
else do;
inv2 = 200;
inv1 = 0;
buy2 = goal - 200 - bal2;
sel1 = bal1 - goal;
end;
bal1 + (buy1 - sel1 + inv1);
bal2 + (buy2 - sel2 + inv2);
output;
end;
stop;
drop company return ;
format bal: 10.4 rate: 5.3;
run;

Get time difference between two times in swift 3

I have 2 variables where I get 2 times from datePicker and I need to save on a variable the difference between them.
let timeFormatter = DateFormatter()
timeFormatter.dateFormat = "HHmm"
time2 = timeFormatter.date(from: timeFormatter.string(from: datePicker.date))!
I have tried to get the timeIntervalSince1970 from both of them and them substract them and get the difference on milliseconds which I will turn back to hours and minutes, but I get a very big number which doesn't corresponds to the actual time.
let dateTest = time2.timeIntervalSince1970 - time1.timeIntervalSince1970
Then I have tried using time2.timeIntervalSince(date: time1), but again the result milliseconds are much much more than the actual time.
How I can get the correct time difference between 2 times and have the result as hours and minutes in format "0823" for 8 hours and 23 minutes?
The recommended way to do any date math is Calendar and DateComponents
let difference = Calendar.current.dateComponents([.hour, .minute], from: time1, to: time2)
let formattedString = String(format: "%02ld%02ld", difference.hour!, difference.minute!)
print(formattedString)
The format %02ld adds the padding zero.
If you need a standard format with a colon between hours and minutes DateComponentsFormatter() could be a more convenient way
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute]
print(formatter.string(from: time1, to: time2)!)
TimeInterval measures seconds, not milliseconds:
let date1 = Date()
let date2 = Date(timeIntervalSinceNow: 12600) // 3:30
let diff = Int(date2.timeIntervalSince1970 - date1.timeIntervalSince1970)
let hours = diff / 3600
let minutes = (diff - hours * 3600) / 60
To get duration in seconds between two time intervals, this can be used -
let time1 = Date(timeIntervalSince1970: startTime)
let time2 = Date(timeIntervalSince1970: endTime)
let difference = Calendar.current.dateComponents([.second], from: time1, to: time2)
let duration = difference.second
Now you can do it in swift 5 this way,
func getDateDiff(start: Date, end: Date) -> Int {
let calendar = Calendar.current
let dateComponents = calendar.dateComponents([Calendar.Component.second], from: start, to: end)
let seconds = dateComponents.second
return Int(seconds!)
}

How to remove weekdays in duration data type NAV

How can i remove weekdays in the data type duration in CAL ?
for example:
duration := datetime2 - datetime1
But duration do contains Saturdays and Sundays. How can i remove them ?
Simple answer: you can not.
But you can use the Date virtual table. Something like this:
Date.SETRANGE("Period Type", Date."Period Type"::Date);
Date.SETFILTER("Period Start", '%1..%2', DT2DATE(datetime1), DT2DATE(datetime2));
Date.SETRANGE("Period No.", 1, 5); // only days 1 - 5 = weekdays
EXIT(Date.COUNT); // returns number of days
You can then convert the number of days to a duration with a simple multiplication. A Duration is nothing more than the number of milliseconds.
1 hour = 3600000ms.
Therefore:
MESSAGE('%1', NoOfDays);
dur := NoOfDays * 24 * 3600 * 1000;
MESSAGE('%1', dur);

How to put colon inbetween elements of a big number using python

My question is my title . I want to put colon to number 2034820. It should look like 2:03:48:20
Basically this is my time data in HHMMSSMS format i.e hour minute second and millisecond.I want to plot other data with respect to this time format. How can I plot my data in y-axis and time of given format in x-axis.
data = numpy.genfromtxt('inputfile.dat') fig=plt.figure()
ax1 = plt.subplot(111) sat1=ax1.plot(data[:,1],'b',linewidth=1,label='SVID-127')
sat2 = ax1.plot(data[:,2],'m-',linewidth=1,label='SVID-128')
Any help is highly appreciated.
Thanks
you can parse the time with datetime.strptime and then re-format it:
from datetime import datetime
tme = datetime.strptime('{:08d}'.format(2034820), '%H%M%S%f').time()
strg = '{0:%H:%M:%S:%f}'.format(tme)
print(strg[:-4]) # cut the trailing '0000'
# 02:03:48:20
this assumes your input is an integer (which will be converted to a zero-padded string of length 8 with '{:08d}'.format(2034820); if the data comes as string you need to convert it to an int first: '{:08d}'.format(int('2034820'))).
from your comments: you seem to be getting the number of seconds that have passed since midnight. for those you could to this:
from datetime import time
def convert(timefloat):
hours, rest = divmod(timefloat, 3600)
mins, rest = divmod(rest, 60)
secs, rest = divmod(rest, 1)
microsecs = int(10**6 * rest)
tme = time(int(hours), int(mins), int(secs), microsecs)
return '{0:%H:%M:%S:%f}'.format(tme)[:-4]
which gives for your test-data:
for d in data:
print(convert(d))
#23:59:59:58
#23:59:59:80
#23:59:59:99
#00:00:00:20
#00:00:00:40
#00:00:00:60