Menkir
DatemathEx - Parser for datemath syntax
DatemathEx
DatemathEx is an Elixir library designed to parse datemath syntax using Combine.
Examples
- Basic addition
iex(1)> DatemathEx.parse "2020-01-01||+1d"
{:ok, ~U[2020-01-02 00:00:00.000Z]}
- Complex Expressions
iex(1)> DatemathEx.parse "2020-01-01T12:24:00||+31d+2h/h"
{:ok, ~U[2020-02-01 14:00:00Z]}
- Relative to Now
iex(1)> DatemathEx.parse "now-1000s/h"
{:ok, ~U[2024-05-16 08:00:00Z]}
- Timezone Offset
iex(1)> DatemathEx.parse "2020-01-01T12:00:00+02:00"
{:ok, ~U[2020-01-01 10:00:00.000000Z]}
- Invalid Syntax
iex(1)> DatemathEx.parse "now*1h"
{:error, "Expected at least one parser to succeed at line 1, column 0."}
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.
Most Liked
Menkir
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.
.
Eiji
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,
choice([
string("now")
|> map({:now, []})
|> post_traverse({:overwrite_now, []})
|> label("UTC now anchor"),
choice([
datetime(),
date()
])
|> label("ISO datetime anchor")
|> ignore_whitespace
|> ignore(string("||"))
])
|> ignore_whitespace
|> parsec(:math_expressions)
|> eos()
|> reduce({:reduce_expressions, []})
With that we can:
- reduce code (by 4 doubled LOC)
- make rule more clear by moving common combinators to the end of pipe and outside of the choice combinator
- make rule more clear by moving
ignore_whitespaceandignore(string/1)combinators after label which says that those are not part of a “ISO datetime anchor”







