DatemathEx - Parser for datemath syntax


DatemathEx is an Elixir library designed to parse datemath syntax using NimbleParsec.


  1. Basic addition
iex(1)> DatemathEx.parse "2020-01-01||+1d"
{:ok, ~U[2020-01-02 00:00:00.000Z]}
  1. Complex Expressions
iex(1)> DatemathEx.parse "2020-01-01T12:24:00||+31d+2h/h"
{:ok, ~U[2020-02-01 14:00:00Z]}

  1. Relative to Now
iex(1)> DatemathEx.parse "now-1000s/h"
{:ok, ~U[2024-05-16 08:00:00Z]}
  1. Invalid Syntax
iex(1)> DatemathEx.parse "now*1h"
{:error, "expected ISO datetime anchor while processing UTC now anchor or ISO datetime anchor"}

Current Limitations

While DatemathEx provides robust functionality for datemath parsing, there are areas where it can be improved:

  • Better Error Reporting: Enhanced error messages to provide more precise feedback on syntax errors and invalid operations.
  • ISO Datetime handling: Improved handling and validation of ISO 8601 datetime strings, ensuring accurate parsing and error detection.
  • Timezone Support: Integration of timezone parsing and manipulation to handle datetime operations across different time zones.

I fully understand why you use nimble_parsec, but if you are already working with timex wouldn’t that be better to use combine instead? That would reduce dependencies as combine would be used anyway.

Not sure if remember nimble_parsec well enough, i.e. not sure if we can use label/2 in the middle of pipeline, but wouldn’t that be a more clear to read parser’s rule?

 defparsec :parse_input,
    |> map({:now, []})
    |> post_traverse({:overwrite_now, []})
    |> label("UTC now anchor"),
    |> label("ISO datetime anchor")
    |> ignore_whitespace
    |> ignore(string("||"))
  |> ignore_whitespace
  |> parsec(:math_expressions)
  |> eos()
  |> reduce({:reduce_expressions, []})

With that we can:

  1. reduce code (by 4 doubled LOC)
  2. make rule more clear by moving common combinators to the end of pipe and outside of the choice combinator
  3. make rule more clear by moving ignore_whitespace and ignore(string/1) combinators after label which says that those are not part of a “ISO datetime anchor”
1 Like

You are absolutely right. I will consider using Combine . For me, it was about learning combinators and using NimbleParsec. The reason for choosing Timex came later when it was about time-shifting. :sweat_smile: .