Hello,
I have Strings representing duration like "0.123"
(in seconds, with millisecond resolution), "1:2.123"
(minute:second.millisecond
), "1:2:3.456"
(hour:minute:second.millisecond
)
I wonder if some functions to parse String
to Dates.CompoundPeriod
exists.
I did my own functions
using Test
using Dates
import Base: parse, tryparse
function parse(::Type{Second}, s)
# s.xxxxxxxxx
n = count(i->(i=='.'), s)
if n == 0
Second(s)
elseif n == 1
s, ns = split(s, ".")
if length(ns) > 9
throw(InexactError)
else
while(length(ns) < 9)
ns = ns * "0"
end
end
Second(s) + Millisecond(ns[1:3]) + Microsecond(ns[4:6]) + Nanosecond(ns[7:9])
else
throw(ArgumentError("invalid s.ms \"$s\""))
end
end
function tryparse(::Type{Second}, s, args... ; kwargs...)
try
parse(Second, s, args... ; kwargs...)
catch
nothing
end
end
@test parse(Second, "4") == Second(4)
@test parse(Second, "4.321") == Second(4) + Millisecond(321)
@test parse(Second, "4.3") == Second(4) + Millisecond(300)
@test parse(Second, "4.300") == Second(4) + Millisecond(300)
@test parse(Second, "4.003") == Second(4) + Millisecond(3)
@test parse(Second, "4.003002") == Second(4) + Millisecond(3) + Microsecond(2)
@test parse(Second, "4.003002001") == Second(4) + Millisecond(3) + Microsecond(2) + Nanosecond(1)
@test parse(Second, "0") == Second(0)
@test parse(Second, "0.0") == Second(0)
@test parse(Second, "0.0") == Dates.CompoundPeriod()
function parse(::Type{Dates.CompoundPeriod}, s::AbstractString)
n = count(i->(i==':'), s)
if n == 0
parse(Second, s)
elseif n == 1 # mm:ss
mm, ss = split(s, ":")
ss = parse(Second, ss)
Minute(mm) + ss
elseif n == 2 # hh:mm:ss
hh, mm, ss = split(s, ":")
ss = parse(Second, ss)
Hour(hh) + Minute(mm) + ss
else
throw(ArgumentError("invalid hh:mm:ss \"$s\""))
end
end
function tryparse(::Type{Dates.CompoundPeriod}, s, args... ; kwargs...)
try
parse(Dates.CompoundPeriod, s, args... ; kwargs...)
catch
nothing
end
end
@test parse(Dates.CompoundPeriod, "4.321") == Second(4) + Millisecond(321)
@test parse(Dates.CompoundPeriod, "5:4.321") == Minute(5) + Second(4) + Millisecond(321)
@test parse(Dates.CompoundPeriod, "6:5:4.321") == Hour(6) + Minute(5) + Second(4) + Millisecond(321)
@test parse(Dates.CompoundPeriod, "0") == Dates.CompoundPeriod()
but I can’t imagine that it doesn’t exist (better written) in either Base or in an existing package.
I’m not looking for parsing as Dates.Time
(because hour can exceed 24).
Any idea?
Kind regards