Packages

Crontab intervals with time collision detection

Current section

Files

Jump to
cronider lib parser.ex
Raw

lib/parser.ex

defmodule Cronider.Parser do
@minutes 60
@hours 24
@months 12
@days_of_month 31
@days_of_week 7
@doc """
Generates cycled range from `lh` to `rh`. The cycle is defined by divisor `div`.
## Example
range (2,5,10) # 2..5
range (5,2,10) # [5,6,7,8,9,0,1,2]
"""
def range(lh, rh, _div) when lh < rh, do: lh..rh
def range(lh, lh, div), do: 0..div-1
def range(lh, rh, div), do: Enum.concat(lh..div-1, 0..rh)
def parse(data) do
data
|> String.split(" ")
|> Enum.zip([:minutes, :hours, :days_of_month, :months, :days_of_week])
|> Enum.map(
fn {sigil, place} -> parse_sigil(sigil, place) end
)
end
def parse_sigil(sigil, place) do
do_parse(sigil|>String.split("-"), place)
end
def do_parse(["*"|[]], place) do
case place do
:minutes -> {place, 0..@minutes-1}
:hours -> {place, 0..@hours-1}
:months -> {place, 0..@months-1}
:days_of_month -> {place, 0..@days_of_month-1}
:days_of_week -> {place, 0..@days_of_week-1}
_ -> raise "Wrong place."
end
end
def do_parse([x|[]], place), do: {place, [String.to_integer(x)]}
def do_parse([x| [y]], place) do
[x,y] = Enum.map([x,y], &String.to_integer/1)
case place do
:minutes -> {place, range(x,y,@minutes)}
:hours -> {place, range(x,y,@hours)}
:months -> {place, range(x,y,@months)}
:days_of_month -> {place, range(x,y,@days_of_month)}
:days_of_week -> {place, range(x,y,@days_of_week)}
_ -> raise "Wrong place."
end
end
end