I got some time intervals using the tic() and toc() functions which are in seconds.
Let's suppose I have a time interval dt=3600.125 seconds. How can I print it in "H:M:S.s" format using Julia?
I got some time intervals using the tic() and toc() functions which are in seconds.
Let's suppose I have a time interval dt=3600.125 seconds. How can I print it in "H:M:S.s" format using Julia?
If you convert it to Dates formats then you can use this method.
julia> t1 = now()
2017-11-10T10:00:51.974
# Wait
julia> t2 = now()
2017-11-10T10:10:07.895
julia> x = Dates.canonicalize(Dates.CompoundPeriod(t2-t1))
9 minutes, 15 seconds, 921 milliseconds
julia> x.periods
3-element Array{Base.Dates.Period,1}:
9 minutes
15 seconds
921 milliseconds
julia> x.periods[2]
15 seconds
julia> x.periods[2].value
18
Have a look at the dates section in the manual.
Not sure if this is the most efficient way, but this works for instance:
julia> Dates.format(DateTime("2017-10-01T01:02:03"), "H:M:S.s")
"1:2:3.0"
You can make your own function. The main function to know is divrem which gives you the divisor as well as the remainder in one convenient function call.
dt=3600.125
function hmss(dt)
(h,r) = divrem(dt,60*60)
(m,r) = divrem(r, 60)
#(s,r) = divrem(r, 60)
string(Int(h),":",Int(m),":",r)
end
hmss(dt)
hmss(3452.98)
""" working properly only if 0<= sec <=86400 otherwise truncating """
function fmtsec(sec, fmt::Dates.DateFormat)
# nanos = Dates.Nanosecond(sec * 1e9) # we could get InexactError here!
nanos = Dates.Nanosecond(trunc(Int, sec * 1e9))
mytime = Dates.Time(nanos)
Dates.format(mytime, fmt)
end
fmt = dateformat"H:M:S.s" # Creating a DateFormat object is expensive. (see doc)
fmtsec(3600.125, fmt) # "1:0:0.125"
EDIT: Without truncating nanoseconds we could get error ->
julia> tic();sleep(1);old_fmtsec(toc(), dateformat"S.s")
elapsed time: 1.002896514 seconds
ERROR: InexactError()
Stacktrace:
[1] convert(::Type{Int64}, ::Float64) at ./float.jl:679
[2] fmtsec(::Float64, ::DateFormat{Symbol("S.s"),Tuple{Base.Dates.DatePart{'S'},Base.Dates.Delim{Char,1},Base.Dates.DatePart{'s'}}}) at ./REPL[47]:2
julia> tic();sleep(1);old_fmtsec(toc(), dateformat"S.s")
elapsed time: 1.002857122 seconds
"1.002"
tic & toc are deprecated. toc could bring rounding error because it internally use time_ns but nanoseconds convert to seconds dividing by 1e9.
This date from toc() and time() in Julia uses UNIX timestamp, i.e., seconds elapsed since January 1, 1970
The same occurs with the function ctime(f) that returns timestamp from a file path f.
The conversion is very straightforward.
tic()
....
dif = toc()
# My local is Brazil, one should replace for its local format
Dt = DateTime(LibC.strftime(dif),"d/m/y H:M:S")
LibC does not have to be imported explicitly
I had a go now, but doing the carry over is a bit messy sorry:
using Dates
using Printf
function formatDuration(duration::Period, types::Vector{DataType}=[Hour, Minute, Second]; addUnit::Bool=false)
periods = canonicalize(Dates.CompoundPeriod(duration)).periods
missingTypes = Vector{DataType}(types)
newPeriods = vcat(periods, map(t->t(0), missingTypes))
sort!(newPeriods; rev=true)
newPeriods1 = Vector{Period}()
carryover = nothing
for (i, p) in enumerate(newPeriods)
typeofp = typeof(p)
if !isnothing(carryover)
newPeriod = convert(typeofp, floor(Millisecond(p) + Millisecond(carryover), typeofp(1)))
carryover = nothing
else
newPeriod = p
end
if (typeof(newPeriod) in types)
push!(newPeriods1, newPeriod)
filter!(e->e≠typeofp,missingTypes)
else
carryover = newPeriod
end
end
m = map(types) do t
f = findfirst(x -> typeof(x) == t, newPeriods1);
r = isnothing(f) ? 0 : newPeriods1[f].value;
@sprintf("%02d",r) * (addUnit ? lowercase("$t"[1]) : "")
end
join(m, ":")
end
Usage examples:
@show formatDuration(Millisecond(3600.125*1000))
# returns "01:00:00"
@show formatDuration(Day(2), [Hour, Minute, Second])
# returns "48:00:00"
@show formatDuration(Second(100000000), [Hour, Minute, Second])
# returns "27777:46:40"
@show formatDuration(Second(100000001), [Day, Hour, Minute, Second, Millisecond])
# returns "1157:09:46:41:00"
@show formatDuration(Millisecond(10000000001),
[Week, Day, Hour, Minute, Second, Millisecond]; addUnit=true)
#returns "16w:03d:17h:46m:40s:01m"