Inconsistent behaviour of Int/Date conversion


#1

Converting from Integers to Dates interprets the relationship differently than converting Dates to Integers. I would assume it to be symmetric. When converting Int -> Date, the integer value 1 is interpreted as 1 year. When converting Date -> Int, one day is interpreted as the integer value 1.

Int(Date(4)) # 1096

Is there a good reason for this behaviour? It has already given me a few (extra) grey hairs.


#2

With Date(4) you are calling the Date(4, m=1, d=1) constructor. Try

convert(Int, convert(Date, 4))

#3

That explains it - but still, shouldn’t Date(4) == convert(Date, 4)?


#4

If this were always true, then there wouldn’t be much utility to having convert at all.

Think of Vector{Int}(10) vs convert(Vector{Int}, 10). What should the latter do?


#5

AFAICT the convention is to use T(...) for various constructors, and convert(T, ...) for conversion. The two may coincide, but they don’t need to. I agree that this generates unfortunate expectations, since many conversions have the T(...) syntax.

Should single-argument constructors enforce T(x) == convert(T, x)? I don’t have a strong opinion on this, but it could avoid some hard to find bugs.


#6

No I agree with that, of course. I was talking about this specific case or similar cases - exactly because of some hard-to-find bugs. I became aware of it because it caused bar_width on Plots.plot to fail when TimeTypes were used on the X axis (cf https://github.com/JuliaPlots/Plots.jl/issues/748)


#7

Yeah, it might be considered bad style to have both methods defined with similar signatures but different behaviour, I dunno. Sometimes it is challenging to avoid, especially if both behaviours are useful.


#8

Yes I guess that is really my key question here - are both behaviours most useful as they are for some specific reason I haven’t thought of - or is this an unintentional design quirk?


#9
Date(::Int)
Int(::Date)

i honestly don’t see what any of these mean intuitively. you can only make sense of these after consulting the documentation. therefore i don’t see any problem with how they behave, no matter what that behavior is. the principle of least surprise does not apply to a situation in which every behavior is equally surprising.


#10

Well, thanks for your input to the discussion.


#11

I guess in general both behaviours can be useful (see the example of @andyferris with Vector{Int} above), but since the latest iterations of the manual seem to promote T(...) for conversion (eg for Int, Float64), I agree that this can be very confusing.


#12

This conversion method is actually dimensionally incorrect and shouldn’t exist. Check if it has been deprecated on v0.6?


#13

Interesting, in fact it is! In 0.6 you need to use Dates.value(Date(4)) #also 1096.