Last active
August 13, 2016 06:21
-
-
Save leesharma/9f251427d020f58c27b3d007904a2442 to your computer and use it in GitHub Desktop.
What is the best practice for matching against bound variables?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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