Skip to content

Instantly share code, notes, and snippets.

@caike
Created March 29, 2023 13:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save caike/46edbcea50fa55c0d8349dc4d50a4af9 to your computer and use it in GitHub Desktop.
Save caike/46edbcea50fa55c0d8349dc4d50a4af9 to your computer and use it in GitHub Desktop.
Elixir Protocols in Practice
##########################################
# Example of using Protocols in Elixir
#
# cat .tool-versions
# elixir 1.14.3
# erlang 24.3.4
#
# Run via: elixir run.exs
#
############################
defprotocol DateEncoder do
@doc """
Defines a common interface for encoding Date-like data.
Returns a date in for ISO-8601 format
"""
@fallback_to_any true
def encode_date(date)
end
defimpl DateEncoder, for: Date do
def encode_date(date) do
case DateTime.new(date, ~T[00:00:00], "Etc/UTC") do
{:ok, datetime} -> DateEncoder.encode_date(datetime)
_ -> {:error, "Error encoding date"}
end
end
end
defimpl DateEncoder, for: DateTime do
def encode_date(date_time) do
date_time
|> DateTime.to_naive()
|> DateEncoder.encode_date()
end
end
defimpl DateEncoder, for: NaiveDateTime do
def encode_date(date) do
to_iso8601(date) <> "Z"
end
defp to_iso8601(date) do
date
|> NaiveDateTime.truncate(:second)
|> NaiveDateTime.to_iso8601(:extended)
end
end
defimpl DateEncoder, for: Any do
def encode_date(value), do: value
end
ExUnit.start()
defmodule DateEncoderTest do
use ExUnit.Case
test "encodes DateTime" do
{:ok, date_time} = DateTime.new(~D[2000-09-03], ~T[13:30:00.000], "Etc/UTC")
expected = "2000-09-03T13:30:00Z"
assert DateEncoder.encode_date(date_time) == expected
end
test "encodes NaiveDateTime" do
{:ok, date_time} = DateTime.new(~D[2000-09-03], ~T[13:30:00.000], "Etc/UTC")
naive_date_time = DateTime.to_naive(date_time)
expected = "2000-09-03T13:30:00Z"
assert DateEncoder.encode_date(naive_date_time) == expected
end
test "encodes Date" do
{:ok, date_time} = DateTime.new(~D[2000-09-03], ~T[13:30:00.000], "Etc/UTC")
date = DateTime.to_date(date_time)
expected = "2000-09-03T00:00:00Z"
assert DateEncoder.encode_date(date) == expected
end
test "encodes Any returns same" do
expected = "banana"
assert DateEncoder.encode_date("banana") == expected
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment