Packages

Human Time is a function to convert a string such as "every other tuesday", "every weekday" or "every friday at 2pm" and convert it into a sequence of date times as allowed by the string.

Current section

Files

Jump to
human_time lib human_time.ex
Raw

lib/human_time.ex

defmodule HumanTime do
@moduledoc """
Human Time is a function to convert a string such as "every other tuesday", "every weekday" or "every friday at 2pm" and convert it into a sequence of date times as allowed by the string.
"""
alias HumanTime.Generators
alias HumanTime.Parser
@doc """
Generates a stream of datetimes for the string given.
## Options
`from` The datetime from when the sequence will be generated, defaults to the current time.
`until` The datetime when the sequence will be terminated, defaults to nil. When nil the sequence will never be terminated.
## Example
HumanTime.parse("Every wednesday at 1530")
|> Stream.take(3)
|> Enum.to_list
#=> [
#=> #DateTime<2018-08-15 15:30:00.848218Z>,
#=> #DateTime<2018-08-22 15:30:00.848218Z>,
#=> #DateTime<2018-08-29 15:30:00.848218Z>
#=> ]
"""
@spec parse(String.t(), [term]) :: Enumerable.t
def parse(timestring, opts \\ []) do
from = opts[:from] || Timex.now()
until = opts[:until]
while_function = Generators.while_function(until)
{generator_function, filter_function, mapper_function} = timestring
|> clean
|> Parser.build_functions
Stream.iterate(from, generator_function)
|> Stream.take_while(while_function)
|> Stream.filter(filter_function)
# |> Stream.map_reduce(mapper_function)
|> Stream.map(mapper_function)
|> Stream.filter(&(&1 != nil))
end
# Removes double-spacing from the string, removes the word
# "every" which is not needed to match against.
# Also downcases the string as we don't want it to have
# to watch for case in the regex
@doc false
@spec clean(String.t()) :: String.t()
defp clean(timestring) do
timestring
|> String.replace("every", "")
|> String.replace(" ", " ")
|> String.replace(" ", " ")
|> String.replace(" ", " ")
|> String.trim
|> String.downcase
end
end