Normal behaviour with second precision:
x_min = DateTime("2016-02-22T16:14:39")
x_max = DateTime("2016-02-22T20:23:51")
x_span = x_max-x_min
println(x_span)
y = x_span/20.0
println(y)
14952000 milliseconds
747600 milliseconds
Behaviour if date times have sub-second precision:
x_min = DateTime("2016-02-22T15:38:45.234")
x_max = DateTime("2016-02-22T19:27:35.363")
x_span = x_max-x_min
println(x_span)
y = x_span/20.0
println(y)
13730129 milliseconds
LoadError: InexactError()
while loading In[51], in expression starting on line 7
in / at dates/periods.jl:49
If you look here https://github.com/JuliaLang/julia/blob/master/base/dates/types.jl#L15-L20
You will see that hours, minutes, seconds, and milliseconds are Int64s
julia> x_min = DateTime("2016-02-22T15:38:45.230")
2016-02-22T15:38:45.23
julia> x_max = DateTime("2016-02-22T19:27:35.360")
2016-02-22T19:27:35.36
julia> x_max-x_min
13730130 milliseconds
julia> (x_max-x_min)/15
915342 milliseconds
julia> (x_max-x_min)/16
ERROR: InexactError()
in /(::Base.Dates.Millisecond, ::Int64) at ./dates/periods.jl:57
in eval(::Module, ::Any) at ./boot.jl:267
So if (x_max-x_min)/y) _also_ is to be a Millisecond type, then it will have to return something that can be represented by an Int64, but then you have to use div
div((x_max-x_min),16)
858133 milliseconds
or (if you really want the decimal number)
(x_max-x_min).value/16
858133.125
Indeed, your first example only works because the division of 14952000 by 20 is exact, so the floating point result is converted without loss to an integer.
Note that instead of div, you can use the corresponding operator 梅 (\div + [tab]).
I understand this can be annoying, especially for newcomers, but Julia usually doesn't do automatic rounding. @quinnj?
I see! Thanks for clarifying.
I did expect rounding in these functions. I'll keep an eye out in the future if non-rounding is the norm for Julia.
That said, it doesn't make much sense to allow using / given that it will fail most of the time. If we don't want to round automatically, we should at least raise an error and tell the user to use 梅. That would avoid this surprising behavior where it works for some values and not for others.
The same problem happens with non-integer multiplication. In that case, we don't have an equivalent of div, so one needs to use round.
This is the reason why I often have to convert DateTimes to unixtime before plotting with a package like Gadfly, since things like boxplots or density plots require / to behave nicely. I'm not sure what a better solution looks like, but DateTimes are fairly painful to work with at the moment.
Boxplots need to compute the mean so I understand why they fail currently, but why would a density plot fail without /?
I just ran into this problem myself when trying to rescale an interval of time by a Float64 (e.g. then = now(); sleep(0.1); (now() - then)/0.1). As has been said in this thread, there's no automatic rounding in Julia, but with ordinary numbers there is automatic promotion, which sets up an expectation for this sort of operation to work. There may be compelling reasons to have Millisecond be integer-based but this doesn't seem like an operation that should result in an error.
This is unexpected - I expected finding the mean between two dates as (b-a)/2 ... and that actually works almost always, until one day ...
The following code
for i in range(1,length=10)
println((DateTime(2000,2,1) - DateTime(2000,1,1)) / i)
end
fails at i==7! ... who'd have guessed that (and would have tested for it?)??
Most helpful comment
I just ran into this problem myself when trying to rescale an interval of time by a Float64 (e.g.
then = now(); sleep(0.1); (now() - then)/0.1). As has been said in this thread, there's no automatic rounding in Julia, but with ordinary numbers there is automatic promotion, which sets up an expectation for this sort of operation to work. There may be compelling reasons to have Millisecond be integer-based but this doesn't seem like an operation that should result in an error.