Skip to content

Commit

Permalink
Added Bithday Validator
Browse files Browse the repository at this point in the history
  • Loading branch information
MICHAELMUNAVU83 committed Dec 5, 2024
1 parent 256bf87 commit 0f10029
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 0 deletions.
102 changes: 102 additions & 0 deletions lib/animina/ birthday_validator.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
defmodule Animina.BirthdayValidator do
@moduledoc """
A module to validate a birthday in the format dd.mm.yy.
"""

@doc """
Validates a birthday string in the format dd.mm.yy.
## Examples
iex> BirthdayValidator.validate_birthday("15.08.95")
{:ok, ~D[1995-08-15]}
iex> BirthdayValidator.validate_birthday("32.01.21")
{:error, "Invalid day for the given month."}
iex> BirthdayValidator.validate_birthday("29.02.21")
{:error, "Invalid day for the given month."}
iex> BirthdayValidator.validate_birthday("15.08.30")
{:error, "Birthday cannot be in the future."}
iex> BirthdayValidator.validate_birthday("15.08.2005")
{:ok, ~D[2005-08-15]}
iex> BirthdayValidator.validate_birthday("15.08.2010")
{:error, "Birthday must be more than 18 years ago."}
"""
def validate_birthday(birthday) do
with {:ok, date_parts} <- parse_birthday(birthday),
{:ok, date} <- validate_date(date_parts),
:ok <- check_not_future(date),
:ok <- check_age(date) do
{:ok, date}
else
{:error, reason} -> {:error, reason}
end
end

defp parse_birthday(birthday) do
case String.split(birthday, ".") do
[day, month, year] ->
case {Integer.parse(day), Integer.parse(month), Integer.parse(year)} do
{{day_int, ""}, {month_int, ""}, {year_int, ""}} ->
{:ok, {day_int, month_int, adjust_year(year_int, String.length(year))}}

_ ->
{:error, "Invalid format. Must be dd.mm.yy or dd.mm.yyyy."}
end

_ ->
{:error, "Invalid format. Must be dd.mm.yy or dd.mm.yyyy."}
end
end

defp adjust_year(year_int, 1), do: 2000 + year_int

defp adjust_year(year_int, 2) do
current_year = Date.utc_today().year
current_two_digits = rem(current_year, 100)

if year_int > current_two_digits do
1900 + year_int
else
2000 + year_int
end
end

defp adjust_year(year_int, 4), do: year_int

defp validate_date({day, month, year}) do
padded_day = String.pad_leading(Integer.to_string(day), 2, "0")
padded_month = String.pad_leading(Integer.to_string(month), 2, "0")

date_str = "#{year}-#{padded_month}-#{padded_day}"

case Date.from_iso8601(date_str) do
{:ok, date} -> {:ok, date}
{:error, _} -> {:error, "Invalid day for the given month."}
end
end

defp check_not_future(date) do
if Date.compare(date, Date.utc_today()) != :gt do
:ok
else
{:error, "Birthday cannot be in the future."}
end
end

defp check_age(date) do
# Calculate the threshold date (18 years ago)
# Approximate 18 years
age_threshold = Date.utc_today() |> Date.add(-18 * 365)

if Date.compare(date, age_threshold) != :gt do
:ok
else
{:error, "Birthday must be more than 18 years ago."}
end
end
end
46 changes: 46 additions & 0 deletions test/animina/birthday_validator_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
defmodule Animina.BirthdayValidatorTest do
use Animina.DataCase, async: true

alias Animina.BirthdayValidator

describe "Tests for the Birthday Validator" do
test "A valid birthday is returned as a date" do
assert {:ok, ~D[1995-08-15]} = BirthdayValidator.validate_birthday("15.08.95")
end

test "An invalid day for the given month returns an error" do
assert {:error, "Invalid day for the given month."} =
BirthdayValidator.validate_birthday("32.01.21")
end

test "A birthday in the future returns an error" do
assert {:error, "Birthday cannot be in the future."} =
BirthdayValidator.validate_birthday("15.08.2030")
end

test "A valid birthday with a 4 digit year is returned as a date" do
assert {:ok, ~D[2005-08-15]} = BirthdayValidator.validate_birthday("15.08.2005")
end

test "A Valid birthday with a 2 digit year returns a date" do
assert {:ok, ~D[2004-08-15]} = BirthdayValidator.validate_birthday("15.08.04")
end

test "A Valid birthday with a 1 digit year returns a date" do
assert {:ok, ~D[2004-08-15]} = BirthdayValidator.validate_birthday("15.08.4")
end

test "A Valid birthday with a 1 digit day returns a date" do
assert {:ok, ~D[2004-08-09]} = BirthdayValidator.validate_birthday("9.08.4")
end

test "A Valid birthday with a 1 digit month returns a date" do
assert {:ok, ~D[2004-08-09]} = BirthdayValidator.validate_birthday("09.8.04")
end

test "A birthday less than 18 years ago returns an error" do
assert {:error, "Birthday must be more than 18 years ago."} =
BirthdayValidator.validate_birthday("15.08.2010")
end
end
end

0 comments on commit 0f10029

Please sign in to comment.