Skip to content

Instantly share code, notes, and snippets.

@leesharma
Last active August 13, 2016 06:21
Show Gist options
  • Save leesharma/9f251427d020f58c27b3d007904a2442 to your computer and use it in GitHub Desktop.
Save leesharma/9f251427d020f58c27b3d007904a2442 to your computer and use it in GitHub Desktop.
What is the best practice for matching against bound variables?
ExUnit.start
defmodule DateParser do
defmodule Timezone, do: defstruct [:full_name, :source]
@doc """
`timezone/2` takes a date/datetime string and a global time zone and returns
a time zone for the specific string. Timezones specified inline should take
priority over the passed-in global timezone.
"""
@spec timezone(String.t, nil | String.t) :: %Timezone{}
def timezone(<< _yyyymmdd :: binary-size(8) >>, _tzid) do
nil
end
def timezone(<< _yyyymmdd :: binary-size(8), "T",
_hhmmss :: binary-size(6) >>, nil) do
nil
end
def timezone(<< _yyyymmdd :: binary-size(8), "T",
_hhmmss :: binary-size(6) >>, tzid) do
%Timezone{full_name: tzid, source: :global}
end
def timezone(<< _yyyymmdd :: binary-size(8), "T",
_hhmmss :: binary-size(6), "Z" >>, _tzid) do
%Timezone{full_name: "UTC", source: :inline}
end
def timezone("TZID=" <> data, _tzid) do
[tzid, date_str] = String.split(data, ":")
case date_str do
<< _yyyymmdd :: binary-size(8), "T", _hhmmss :: binary-size(6) >> ->
%{timezone(date_str, tzid) | source: :inline}
end
end
end
defmodule DateParser.Test.Utils do
@moduledoc """
Contains utility functions to be used in tests, such as `subset?/2`
"""
@doc """
Returns true if all the key-value pairs in `subset` are present in `superset`
"""
@spec subset?(map | nil, struct | nil) :: boolean
def subset?(nil, nil), do: true
def subset?(nil, _), do: false
def subset?(_, nil), do: false
def subset?(%{} = subset, %{} = superset) do
superset_contains_pair = fn {k, v} ->
%{superset | k => v} === superset
end
subset |> Enum.all?(superset_contains_pair)
end
defmacro assert_subset(subset, superset) do
quote do
assert subset?(unquote(subset), unquote(superset)),
"Expected #{inspect unquote(subset)} to be a subset of #{inspect unquote(superset)}"
end
end
end
defmodule DateParser.Test do
use ExUnit.Case
import DateParser.Test.Utils
utc_tzmatch = %{full_name: "UTC"}
new_york_tzmatch = %{full_name: "America/New_York"}
chicago_tzmatch = %{full_name: "America/Chicago"}
expected_time_zones = [
#--------------------------------------+-----------------------------------+
# Input Datestring | Timezone When Global TZID = ? |
# | nil | America/New_York |
#--------------------------------------+-----------------------------------+
[ "19690620", nil, nil,],
[ "19690620T201804", nil, new_york_tzmatch,],
[ "19690620T201804Z", utc_tzmatch, utc_tzmatch,],
["TZID=America/Chicago:19690620T201804", chicago_tzmatch, chicago_tzmatch,],
]
describe "DateParser.timezone(date_string, tzid)," do
for [input, no_tzid, global_tzid] <- expected_time_zones do
@tag input: input
@tag tzmatch: no_tzid
test ~s(date_string: "#{input}", tzid: nil),
%{input: input, tzmatch: tzmatch} do
timezone = DateParser.timezone(input, nil)
assert_subset tzmatch, timezone
end
@tag input: input
@tag tzmatch: global_tzid
test ~s(date_string: "#{input}", tzid: "America/New_York"),
%{input: input, tzmatch: tzmatch} do
timezone = DateParser.timezone(input, "America/New_York")
assert_subset tzmatch, timezone
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment