I have a string containing a date in the form DD.MM.YYYY and would like to convert it to the format YYYYMMDD. No error checking is necessary, since I can ensure that the input string has the correct format. How can this be done in an compact way? NOTE: I'm interested in a solution doing it purely based on string processing, and not in creating and formatting Date
objects.
I came up with the straightforward solution
s ="14.04.2023"
sx = String.slice(s, 6, 4) <> String.slice(s, 3, 2) <> String.slice(s, 0, 2)
This works, but there is a lot of typing. Is there a more "Elixir-like" approach? For instance, in Ruby I would perhaps do a
sx = s.match(/(..).(..).(....)/).captures.reverse.join
which would be clearer IMO, because the regex shows which parts of the string are extracted, and the reverse.join
tells us how these parts are put together again. I wonder how a similar approach would be done in Elixir, or how experienced Elixir programmer would approach this task.
As Everett pointed out, binary pattern matching is the best way to approach this. Compared to Regular expressions it's much more explicit, reliable, and efficient.
def format(<<dd::binary-2, ".", mm::binary-2, ".", yyyy::binary-4>>) do
yyyy <> mm <> dd
end
Using it:
iex(1)> Example.format("14.04.2023")
"20230414"
It also gives you a FunctionClauseError if you pass an invalid value:
iex(2)> Example.format("14.04.23")
** (FunctionClauseError) no function clause matching in Example.format/1
The following arguments were given to Example.format/1:
# 1
"14.04.23"
You could also simplify your answer with String.split
, but I think the binary matching is better. Some people find it hard to understand, so may prefer this, though:
iex(3)> "14.04.2023" |> String.split(".") |> Enum.reverse() |> Enum.join()
"20230414"