1

Hello I was trying to understand how to work with binaries in Elixir and I was trying to parse a string

"2018-04-07 13:00:00.000000"

I wanted to get they year part and I did the following

date = "2018-04-07 13:00:00.000000"
<< d::size(80), rest::binary >> = date

now when I try to get rest I get everything after the date including space

" 13:00:00.000000"

but if I try to get d I don't really understand what I get but the output is the following

237007314493411930484791

Can you guys please help understand what is going.

Thank you.

2 Answers 2

5

While the answer provided by Kevin Johnson perfectly explains how to handle binaries, I will post the explanation of what really happened.

The binary in Erlang (and hence in Elixir) might be created using ASCII values for chars:

iex|1 ▶ <<50, 48>>
#⇒ "20"

When you pattern matched to size(80) you actually pattern matched to 10 positions of the integer in 256-base. Basically, this is what happened:

iex|2 ▶ <<a1::size(8), a2::size(8), a3::size(8),
          a4::size(8), a5::size(8), a6::size(8),
          a7::size(8), a8::size(8), a9::size(8),
          a10::size(8), _ :: binary>> = "2018-04-07 13..."
#⇒ "2018-04-07 13..."

Let’s check our values (yes, the array of integers is printed out as a bitstring whenever possible, note single quotes):

iex|3 ▶ [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10] 
#⇒ '2018-04-07'

OK, so far so good. Let’s now get the result out of the above integers. It would be:

a10 * 1 + a9 * 256 + a8 * 256² + ...

or, using the limited Elixir arithmetical abilities:

iex|4 ▶ [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]
...|4 ▷ |> Enum.reverse
...|4 ▷ |> Enum.with_index
...|4 ▷ |> Enum.reduce(0, fn {e, i}, acc ->
...|4 ▷                     # ⇓⇓⇓ exact integer i-power of 256 ⇓⇓⇓
...|4 ▷      acc + e * Enum.reduce(List.duplicate(256, i), 1, &Kernel.*/2)
...|4 ▷ end)
#⇒ 237007314493411930484791

This is exactly what you yielded when have asked to pattern match first 10 positions to 256-based 10-digit number.

Sign up to request clarification or add additional context in comments.

1 Comment

Great explanation of what happened. Very helpful!
4

The solution to your problem is to use binary-size as follows: << d::binary-size(10), rest::binary >> = date

Following excerpt of the documentation should clarify accordingly:

A bitstring is made of many segments and each segment has a type. There are 9 types used in bitstrings: - integer - float - bits (alias for bitstring) - bitstring - binary - bytes (alias for binary) - utf8 - utf16 - utf32 When no type is specified, the default is integer

For instance, << d::integer-size(80), rest::binary >> = date would have given you the same result as you reported.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.