# Range of Date without a defined step (unit step supposed)

**URL:** <https://discourse.julialang.org/t/range-of-date-without-a-defined-step-unit-step-supposed/54734>\
**Category:** General Usage\
**Created:** [February 6, 2021, 2:37pm UTC](https://discourse.julialang.org/t/range-of-date-without-a-defined-step-unit-step-supposed/54734 "2021-02-06T14:37:26Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![scelles](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scelles/32/220408_2.png) [@scelles](https://discourse.julialang.org/u/scelles)\
**Post date:** [February 6, 2021, 2:37pm UTC](https://discourse.julialang.org/t/range-of-date-without-a-defined-step-unit-step-supposed/54734/1 "2021-02-06T14:37:26Z")

</div>

Hello,

The following code raises an error

```julia
julia> Date(2020,1,1):Date(2020,2,1)
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type Day
Closest candidates are:
  convert(::Type{Day}, ::Week) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Dates\src\periods.jl:410
  convert(::Type{Day}, ::Hour) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Dates\src\periods.jl:418
  convert(::Type{Day}, ::Minute) at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Dates\src\periods.jl:418
  ...
Stacktrace:
 [1] oftype(::Day, ::Int64) at .\essentials.jl:367
 [2] (::Colon)(::Date, ::Date) at .\range.jl:7
 [3] top-level scope at REPL[99]:100: 

```

but not

```julia
Date(2020,1,1):Dates.Day(1):Date(2020,2,1)

```

My opinion is that current implementation of `range` assume an integer step of 1 but it should assume what a unit step of a `Date` is.

I’m facing a similar issue with some custom struct also, not only `Date`.

Maybe the default unit step could be calculated in most cases using

```julia
julia> start = Date(2020,1,1)
2020-01-01

julia> stop = Date(2020,2,1)
2020-02-01

julia> (stop - start) / (stop - start).value
1 day

```

or by defining a `unit(::Type{Date})` or a `unit(::Date)` function

What is you opinion about that?

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [February 6, 2021, 4:26pm UTC](https://discourse.julialang.org/t/range-of-date-without-a-defined-step-unit-step-supposed/54734/2 "2021-02-06T16:26:42Z")

</div>

I dislike it.

What would you want it to assume for and evaluate this?  
`Date(2020,2):Date(2020,5)`

Also, the default step is 1 even in instances where 1 clearly doesn’t make sense (see `0.1:0.5`). There is no logic, it isn’t a calculated default, it is just a default value. If you want the step to be something else, you have to change it.

---

<div class="post-metadata">

**Author:** ![scelles](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scelles/32/220408_2.png) [@scelles](https://discourse.julialang.org/u/scelles)\
**Post date:** [February 6, 2021, 6:11pm UTC](https://discourse.julialang.org/t/range-of-date-without-a-defined-step-unit-step-supposed/54734/3 "2021-02-06T18:11:32Z")

</div>

> What would you want it to assume for and evaluate this?  
> `Date(2020,2):Date(2020,5)`

For `Date(2020,2):Date(2020,5)` or `Date(2020,2,1):Date(2020,5,1)` I would simply assume that the unit step of a `Date` is a `Day`… why ? simply because between 2 consecutive days a day occurs.

For any discrete variable I would assume that step is resolution ie the smallest difference between 2 consecutive values.

But for any number which inherit from `AbstractFloat` that’s a bit different, I would assume step is 1.0.

Maybe having an interface to define what default “unit step” should be for a given type will help.

You can find my use case [GitHub - scls19fr/AIRAC.jl: Julia library to deal with AIRAC cycle dates](https://github.com/scls19fr/AIRAC.jl)

I can have 2 `Airac` struct (an AIRAC cycle duration is 28 days)

```julia
julia> using AIRAC
julia> a1 = parse(Airac, "2101")
Airac(2101, 2021-01-28)

julia> a2 = parse(Airac, "2103")
Airac(2103, 2021-03-25)

```

I can compute the difference between 2 AIRAC cycles and it returns an `AiracDiff` (which simply contains an integer… the number of 28 days durations between the 2 Airac data)

```julia
julia> a2 - a1
AiracDiff(2)

```

but I can’t get simply a range

```julia
julia> a1:a2
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type AiracDiff
Closest candidates are:
  convert(::Type{T}, ::T) where T at essentials.jl:171
  AiracDiff(::Int64) at C:\Users\Admin-pc\.julia\dev\AIRAC\src\AIRAC.jl:93
  AiracDiff(::Any) at C:\Users\Admin-pc\.julia\dev\AIRAC\src\AIRAC.jl:93
Stacktrace:
 [1] oftype(::AiracDiff, ::Int64) at .\essentials.jl:367
 [2] (::Colon)(::Airac, ::Airac) at .\range.jl:7
 [3] top-level scope at REPL[7]:1

```

Same problem also occurs when specifying step.

```julia
julia> a1:AiracDiff():a2
ERROR: MethodError: no method matching -(::Airac, ::Int64)
Closest candidates are:
  -(::Base.CoreLogging.LogLevel, ::Integer) at logging.jl:117
  -(::Missing, ::Number) at missing.jl:115
  -(::Airac, ::AiracDiff) at C:\Users\Admin-pc\.julia\dev\AIRAC\src\AIRAC.jl:120
  ...
Stacktrace:
 [1] steprange_last(::Airac, ::AiracDiff, ::Airac) at .\range.jl:235
 [2] StepRange at .\range.jl:205 [inlined]
 [3] StepRange at .\range.jl:256 [inlined]
 [4] _colon at .\range.jl:46 [inlined]
 [5] (::Colon)(::Airac, ::AiracDiff, ::Airac) at .\range.jl:40
 [6] top-level scope at REPL[8]:1

```

The reason why `range` function would like to convert an `Airac` to `Int64` is really weird to me.

I understand that I can directly overload `range` definition. But that shouldn’t be necessary if we could defined what a unit step is for a given type.

Feel free to provide some implementation idea.

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [February 6, 2021, 10:29pm UTC](https://discourse.julialang.org/t/range-of-date-without-a-defined-step-unit-step-supposed/54734/4 "2021-02-06T22:29:06Z")

</div>

> [@scelles](#):
>
> For any discrete variable I would assume that step is resolution ie the smallest difference between 2 consecutive values.

You say this but then you quickly prove how inconvenient this would be. For example, the smallest unit of difference between 2 consecutive floats is not 1.0, but epsilon. This would be a terrible default of course! So you would prefer 1.0 there. But what about the range I suggested? A default of 1.0 doesn’t make sense there either.

The smallest unit of difference between 2 dates is actually…nanoseconds? picoseconds? But you would prefer 1 day (why not 24 hours?)

The issue is that the appropriate default is context dependent, and (I’m guessing) that is why it is required to be specified.

---

<div class="post-metadata">

**Author:** ![FPGro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fpgro/32/20822_2.png) [@FPGro](https://discourse.julialang.org/u/FPGro)\
**Post date:** [February 6, 2021, 11:38pm UTC](https://discourse.julialang.org/t/range-of-date-without-a-defined-step-unit-step-supposed/54734/5 "2021-02-06T23:38:18Z")

</div>

> [@scelles](#):
>
> Same problem also occurs when specifying step.
> 
> ```julia-auto
> julia> a1:AiracDiff():a2
> ERROR: MethodError: no method matching -(::Airac, ::Int64)
> Closest candidates are:
> -(::Base.CoreLogging.LogLevel, ::Integer) at logging.jl:117
> -(::Missing, ::Number) at missing.jl:115
> -(::Airac, ::AiracDiff) at C:\Users\Admin-pc\.julia\dev\AIRAC\src\AIRAC.jl:120
> ...
> Stacktrace:
> [1] steprange_last(::Airac, ::AiracDiff, ::Airac) at .\range.jl:235
> [2] StepRange at .\range.jl:205 [inlined]
> [3] StepRange at .\range.jl:256 [inlined]
> [4] _colon at .\range.jl:46 [inlined]
> [5] (::Colon)(::Airac, ::AiracDiff, ::Airac) at .\range.jl:40
> [6] top-level scope at REPL[8]:1
> 
> ```
> 
> The reason why `range` function would like to convert an `Airac` to `Int64` is really weird to me

You could take a look at the code. Most likely `rem(::AiracDiff, ::AiracDiff)` returns an `Int`

> [@scelles](#):
>
> I understand that I can directly overload `range` definition. But that shouldn’t be necessary if we could defined what a unit step is for a given type.

~~Theres `oneunit()` and `UnitRange`, I think you can do something like that already, just not necessarily with the colon syntax.~~ Okay, `UnitRange` is for Reals only, my bad.

The “1-colon-syntax” for ranges uses `oftype(stop-start, 1)` as a default value for the stepsize, so you can either overload that or `convert` with your respective types.
