collect(Iterators.take(itr, 10)) returns a Vector of Any (instead of Vector of Date or DateTime)

question
dates

#1

Hello,

I’m working on adjuster functions https://docs.julialang.org/en/stable/manual/dates/#Adjuster-Functions-1
and would like to build an iterator of Date (or DateTime) respecting some date adjusting rules.

Here is my code

import Base: start, done, next
import Base: iteratorsize, IsInfinite

struct DateIterator
    func::Function
    dt::Dates.TimeType
end
start(itr::DateIterator) = itr.dt
done(itr::DateIterator, state) = false
function next(itr::DateIterator, state)
    state = Dates.tonext(itr.func, state)
    state, state
end
iteratorsize(::Type{DateIterator}) = IsInfinite()
#eltype(it::DateIterator) = typeof(it.dt)


dt = Date(2014,7,13)
istuesday = x->Dates.dayofweek(x) == Dates.Tuesday
itr = DateIterator(istuesday, dt)

#state = start(itr)
#while !done(itr, state)
#    dt, state = next(itr, state)
#    println(dt)
#end

#for (i, dt) in enumerate(itr)
#    println(dt)
#    if i == 10
#        break
#    end
#end

println(collect(Iterators.take(itr, 10)))

My issue is that I get a vector of Any.

Any[2014-07-15, 2014-07-22, 2014-07-29, 2014-08-05, 2014-08-12, 2014-08-19, 2014-08-26, 2014-09-02, 2014-09-09, 2014-09-16]

How to have a vector of Date (or DateTime)?

Kind regards


#2

The element type is not inferable because the types of fields of the DateIterator type are abstract.
In this case, I think you can use parameterized type definition:

struct DateIterator{F<:Function,T<:Dates.TimeType}
    func::F
    dt::T
end  

#3

Thanks @bicycle1885 but it doesn’t help
Here is my code:

import Base: start, done, next
import Base: iteratorsize, IsInfinite

struct DateIterator{F<:Function,T<:Dates.TimeType}
    func::F
    dt::T
end  
start(itr::DateIterator) = itr.dt
done(itr::DateIterator, state) = false
function next(itr::DateIterator, state)
    state = Dates.tonext(itr.func, state)
    state, state
end
iteratorsize{T<:DateIterator}(::Type{T}) = IsInfinite()

dt = Date(2014,7,13)
istuesday = x->Dates.dayofweek(x) == Dates.Tuesday
itr = DateIterator(istuesday, dt)

println(collect(Iterators.take(itr, 10)))

#4

Oh, sorry. I replied before checking the result.

Adding a line Base.eltype(::Type{DateIterator{F,T}}) where {F,T} = T to the next of the iteratorsize definition will make it work:

import Base: start, done, next
import Base: iteratorsize, IsInfinite

struct DateIterator{F<:Function,T<:Dates.TimeType}
    func::F
    dt::T
end  
start(itr::DateIterator) = itr.dt
done(itr::DateIterator, state) = false
function next(itr::DateIterator, state)
    state = Dates.tonext(itr.func, state)
    state, state
end
iteratorsize{T<:DateIterator}(::Type{T}) = IsInfinite()
Base.eltype(::Type{DateIterator{F,T}}) where {F,T} = T

dt = Date(2014,7,13)
istuesday = x->Dates.dayofweek(x) == Dates.Tuesday
itr = DateIterator(istuesday, dt)

println(collect(Iterators.take(itr, 10)))

output:

Date[2014-07-15, 2014-07-22, 2014-07-29, 2014-08-05, 2014-08-12, 2014-08-19, 2014-08-26, 2014-09-02, 2014-09-09, 2014-09-16]

#5

Thanks @bicycle1885 you fixed my issue!