Skip to content

Instantly share code, notes, and snippets.

@fishtreesugar
Last active July 3, 2016 08:23
Show Gist options
  • Save fishtreesugar/8da90b6c06918b4e429b513c24cfaaaf to your computer and use it in GitHub Desktop.
Save fishtreesugar/8da90b6c06918b4e429b513c24cfaaaf to your computer and use it in GitHub Desktop.
util functions in Elixir for Chinese ID
defmodule CnId do
defp parse!(id) do
<<adcode :: 6-bytes, year :: 4-bytes, month :: 2-bytes, day :: 2-bytes, seq_code :: 3-bytes, check_code :: 1-bytes>> = id
%{
adcode: adcode,
birthday: Date.from_iso8601!("#{year}-#{month}-#{day}"),
seq_code: seq_code,
check_code: check_code
}
end
def checksum(id) do
<<info :: 17-bytes, check_code :: 1-bytes>> = id
Stream.iterate(18, &(&1 - 1))
|> Stream.zip(String.to_charlist(info))
|> Enum.reduce(0, fn {index, char}, acc ->
n = char - ?0
acc + n * rem(round(:math.pow(2, index - 1)), 11)
end)
|> (&(rem(12 - rem(&1, 11), 11))).()
|> (&(if &1 < 10, do: to_string(&1), else: "X")).()
end
def validate?(id) do
<<info :: 17-bytes, check_code :: 1-bytes>> = id
checksum(id) == check_code
end
def adcode(id) do
parse!(id).adcode
end
def seq_code(id) do
parse!(id).seq_code
end
def birthday(id) do
parse!(id).birthday
end
def gender(id) do
seq_code(id)
|> Integer.parse
|> elem(0)
|> rem(2)
|> (&(if &1 == 0, do: :female, else: :male)).()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment