Inconsistent behaviour of Int/Date conversion

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.

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

convert(Int, convert(Date, 4))

That explains it - but still, shouldn’t Date(4) == convert(Date, 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?

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.

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)

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.

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?

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.

Well, thanks for your input to the discussion.

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.

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

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