Simple (I hope): how to sum the Time column (d) of 15:52:31 + 15:52:31 + 15:52:31 giving 47:34:33
Your current type is Time
, which is a time in a day. You canβt add two times in a day together.
What you want is a Period
julia> t1 = Dates.CompoundPeriod(Hour(15), Minute(52), Second(31));
julia> t2 = Dates.CompoundPeriod(Hour(2), Minute(25), Second(10));
julia> t1 + t2
17 hours, 77 minutes, 41 seconds
NB: the sum should be 47:37:33
Also, the addition of CompoundPeriods does not seem sufficient:
t1 = Dates.CompoundPeriod(Hour(15), Minute(52), Second(31))
t1 + t1 + t1
45 hours, 156 minutes, 93 seconds
One attempt here below, based on this Rosetta code:
using Dates, DataFrames
function HHMMSS_duration(sec)
t = Int[]
for dm in (60, 60)
sec, m = divrem(sec, dm)
pushfirst!(t, m)
end
pushfirst!(t, sec)
return Dates.CompoundPeriod(Hour(t[1]), Minute(t[2]), Second(t[3]))
end
df = DataFrame(a=1:3, d=Dates.Time.(["15:52:31","15:52:31","15:52:31"], "H:M:S"))
s = cumsum(Dates.value.(df.d))/1e9
df.cumsum = HHMMSS_duration.(s)
julia> df
Row β a d cumsum
β Int64 Time Compoundβ¦
ββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββ
1 β 1 15:52:31 15 hours, 52 minutes, 31 seconds
2 β 2 15:52:31 31 hours, 45 minutes, 2 seconds
3 β 3 15:52:31 47 hours, 37 minutes, 33 seconds
canonicalize
might help. It does what its name implies or what this example shows:
julia> cp = Dates.CompoundPeriod(Hour(2),Minute(100),Second(5))
2 hours, 100 minutes, 5 seconds
julia> canonicalize(cp)
3 hours, 40 minutes, 5 seconds
If we take the OP example, it produces:
t1 = Dates.CompoundPeriod(Hour(15), Minute(52), Second(31))
canonicalize(t1 + t1 + t1)
1 day, 23 hours, 37 minutes, 33 seconds
Adding times of the day makes no sense. (15:00)*3=45:00
assumes that there is something special about midnight, but it just depends on which offset you choose.
Of course it doesnβt, and Peter already mentioned it above: a different type should be used. Meanwhile, if we reinterpret them as durations, how can we proceed?
Time
is essentially nanoseconds so this should work?
julia> t1 = Time(15, 52, 31)
julia> t2 = Time(15, 52, 31)
julia> t3 = Time(15, 52, 31)
julia> canonicalize(t1.instant + t2.instant + t3.instant)
1 day, 23 hours, 37 minutes, 33 seconds
Thank you all and so I did two things with the second function feeling rather clumsyβ¦(but Iβm learning stuff). Q. How do you pass a data column name by reference to a function i.e. total_time(accepted.Time).
βTotal a dataframe Time column in Weeks, Days, Hours, Minutes and Secondsβ
function total_time_formal(xxx)
t = Dates.CompoundPeriod(Hour(0), Minute(0), Second(0))
for i in 1:nrow(xxx)
t += Dates.CompoundPeriod(xxx.Time[i])
end
return canonicalize(t)
end
βTotal a dataframe Time column for HH:MM:SS i.e. hundreds of hours:minutes:secondsβ
function total_time()
t1 = t2 = t3 = 0.0 # hours, minutes, seconds
for i in 1:nrow(accepted)
t1 += Dates.hour(accepted.Time[i])
t2 += Dates.minute(accepted.Time[i])
t3 += Dates.second(accepted.Time[i])
end
t2 += modf(t3 / 60)[2] # whole seconds to minutes
t3 = modf(t3 / 60)[1] * 60 # residual seconds
t1 += modf(t2 / 60)[2] # whole minutes to hours
t2 = modf(t2 / 60)[1] * 60 # residual minutes
return t1, t2, t3
end
Another way to convert higher periods (days, weeks) to hours:
julia> hourify(t) = begin
tt = canonicalize(t) ;
pushfirst!(tt.periods, sum(Hour.(splice!(tt.periods,1:findlast(in([Hour,Day,Week]), typeof.(tt.periods))))))
end
hourify (generic function with 1 method)
julia> hourify(Second(123121414))
3-element Vector{Period}:
34200 hours
23 minutes
34 seconds
The positive about this method is keeping the calculations hidden at the Dates module. Perhaps the technique willl be of sum use.