Interpolate DateTime without InexactError

Hello,

I need to interpolate DateTime

I have a function like

function interpolate_time(x1::Float64, t1::DateTime, x2::Float64, t2::DateTime, xI::Float64)
    return (xI - x1) / (x2 - x1) * (t2 - t1) + t1
end
interpolate_time(0.0, DateTime(2019, 1, 1), 2.0, DateTime(2019, 1, 1, 0, 0, 40), 1.0)
2019-01-01T00:00:20

works fine but

> interpolate_time(0.0, DateTime(2019, 1, 1), 2.0, DateTime(2019, 1, 1, 0, 0, 40), 1.5)

raises an InexactError

ERROR: InexactError: Int64(1.5)
Stacktrace:
 [1] Type at ./float.jl:703 [inlined]
 [2] * at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Dates/src/periods.jl:92 [inlined]
 [3] * at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Dates/src/periods.jl:93 [inlined]
 [4] interpolate_time(::Float64, ::DateTime, ::Float64, ::DateTime, ::Float64) at ./REPL[9]:2
 [5] top-level scope at none:0

How to perform such an interpolation (accepting a 1 millisecond error)?

I noticed that there is a package named Interpolations.jl (pinging @tim.holy )

but I don’t know if it can handle that and/or if that’s not overkilled for that purpose (it’s a simple linear interpolation here)

Kind regards

This should fit the bill:

using Dates
function interpolate_time(x1, t1::DateTime, x2, t2::DateTime, xI)
    Δ = Dates.value(t2 - t1)
    Millisecond(round(Int, Δ*(xI - x1)/(x2 - x1))) + t1
end
julia> interpolate_time(0, DateTime(2019, 1, 1), 2, DateTime(2019, 1, 1, 0, 0, 40), 1.5)
2019-01-01T00:00:30

Other options than round would be floor or ceil depending on whether you want to always round to the nearest, lowest or highest Int respectively.

2 Likes

Thanks @anowacki for your help.

I wonder what is the highest interval between 2 times which is allowed by such a function.

xI beeing between x1 and x2, (xI - x1)/(x2 - x1) is between 0 and 1

So I did

> typemax(Millisecond)
9223372036854775807 milliseconds

to have an idea… but maybe we can have a more human readable value?

Let’s find out the date from the year 0 (if it existed!) when typemax(Millisecond) ms have elapsed:

julia> DateTime(0) + typemax(Millisecond)
292277024-08-17T07:12:55.807

That’s about 292 million years.

1 Like

simple and efficient. I won’t be there to see if Julia is still useful. Thanks again.