# Resolve ambiguous date comparisons with possible missing return?

**URL:** <https://discourse.julialang.org/t/resolve-ambiguous-date-comparisons-with-possible-missing-return/113409>\
**Category:** General Usage\
**Created:** [April 23, 2024, 9:28pm UTC](https://discourse.julialang.org/t/resolve-ambiguous-date-comparisons-with-possible-missing-return/113409 "2024-04-23T21:28:29Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![croberts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/croberts/32/9465_2.png) [@croberts](https://discourse.julialang.org/u/croberts)\
**Post date:** [April 23, 2024, 9:28pm UTC](https://discourse.julialang.org/t/resolve-ambiguous-date-comparisons-with-possible-missing-return/113409/1 "2024-04-23T21:28:29Z")

</div>

Opinion:

Some Date comparisons are, in certain contexts, ambiguous. The Julia Dates package refrains from defining operations where these operations are ambiguous. For example:

```julia
using Dates 

max(Quarter(1), Month(1)) # returns Month(1), as expected 
max(Day(1), Month(1)) # throws exception, probably because there exist comparisons, like max(Day(30), Month(1)), which are ambiguous

```

But why not define

```julia
Base.isless(x::Day, y::Year) = x.value < 365*y.value ? true : (x.value > 366*y.value ? false : missing) # type piracy 

```

Alternatively, throw an error instead of returning a missing.

This would be especially useful when people want to take into account frequency.

Why it would be useful:  
Throwaway pseudo code, but suppose we have something like

```julia
struct TimeSeries{T, STEP} where {T, STEP} 
   data::AbstractVector 
   sr::StepRange 
end 
TimeSeries(av::AbstractVector{T}, sr::StepRange) where T= TimeSeries{T, sr.step}(av, sr)

```

And we want to conveniently compute covariances between variables at different frequencies. Suppose one is daily and one is monthly. Default fallback might take the lowest frequency step and aggregate/subsample from the higher frequency data. Determining which is lower frequency could be handled by max(ts1.sr.step, ts2.sr.step) – except this is not defined for some pairs of DatePeriod types.

Similarly, suppose you want to be able to subsample a quarterly frequency steprange from a monthly timeseries. That can be accomodated by max. But If you build this syntax want to subsample from Date(Year(2010)):Date(Year(2020)), this defaults to a Day(1) stepsize, which cannot be compared with a month.

As a user, this is not hard to deal with but it is annoying, and it would be obviated by comparisons that give the correct answer when the comparison is unambiguous. I’ve done type piracy to get around this, but type piracy is generally not a good idea.

Thanks!

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [April 23, 2024, 10:32pm UTC](https://discourse.julialang.org/t/resolve-ambiguous-date-comparisons-with-possible-missing-return/113409/2 "2024-04-23T22:32:03Z")

</div>

On [one of those](https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b923ca) “falsehoods programmers believe about time” lists I see

> - Years have 365 or 366 days.

I wish these lists would provide the counterexamples to prove their point but this one doesn’t so idk if it’s right.

There is also something nice about having functions that always return a value (never fail). Returning `missing` would make it type-unstable.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [April 23, 2024, 11:40pm UTC](https://discourse.julialang.org/t/resolve-ambiguous-date-comparisons-with-possible-missing-return/113409/3 "2024-04-23T23:40:06Z")

</div>

> [@jar1](#):
>
> I wish these lists would provide the counterexamples to prove their point

Only marginally related, but on the topic of addresses some time ago I came across a similar list, [Falsehoods programmers believe about addresses](https://www.mjt.me.uk/posts/falsehoods-programmers-believe-about-addresses/), which does have counterexamples.

> [@jar1](#):
>
> but this one doesn’t so idk if it’s right.

If I have to make a guess, it could refer to the fact the years on which there was the switch from the Julian to the Gregorian calendar, which is different country by country, had 10-13 days less, depending on when the switch happened.

---

<div class="post-metadata">

**Author:** ![croberts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/croberts/32/9465_2.png) [@croberts](https://discourse.julialang.org/u/croberts)\
**Post date:** [April 24, 2024, 6:08pm UTC](https://discourse.julialang.org/t/resolve-ambiguous-date-comparisons-with-possible-missing-return/113409/4 "2024-04-24T18:08:30Z")

</div>

> [@giordano](#):
>
> If I have to make a guess, it could refer to the fact the years on which there was the switch from the Julian to the Gregorian calendar, which is different country by country, had 10-13 days less,

Okay, then we write

```julia
Base.isless(x::Day, y::Year) = 
    x.value < 365*y.value - 13 ? true : 
                                 (x.value > 366*y.value ? false : 
                                                          throw(AssertionError("Ambiguous DatePeriod comparison"))) # type piracy 

```
