From decc5b95e03cc732b8e1a074bafef37a5cb3726d Mon Sep 17 00:00:00 2001 From: Jakub Polak Date: Sat, 27 Jan 2024 23:06:18 +0100 Subject: [PATCH] Add ATIN (U.S. Adoption Taxpayer Identification Number). --- lib/us/atin.ml | 18 ++++++++++++++++++ lib/us/atin.mli | 22 ++++++++++++++++++++++ lib/us/dune | 4 ++++ test/us/dune | 4 ++++ test/us/test_atin.ml | 24 ++++++++++++++++++++++++ 5 files changed, 72 insertions(+) create mode 100644 lib/us/atin.ml create mode 100644 lib/us/atin.mli create mode 100644 lib/us/dune create mode 100644 test/us/dune create mode 100644 test/us/test_atin.ml diff --git a/lib/us/atin.ml b/lib/us/atin.ml new file mode 100644 index 0000000..dd9e14b --- /dev/null +++ b/lib/us/atin.ml @@ -0,0 +1,18 @@ +exception Invalid_format + +let atin_re = Str.regexp "^9\\([0-9][0-9]\\)-93-\\([0-9][0-9][0-9][0-9]\\)$" + +let validate number = + if Str.string_match atin_re number 0 then number else raise Invalid_format + +let is_valid number = + try + ignore (validate number); + true + with Failure _ -> false + +let format_number number = + if String.length number = 9 then + String.sub number 0 3 ^ "-" ^ String.sub number 3 2 ^ "-" + ^ String.sub number 5 4 + else number diff --git a/lib/us/atin.mli b/lib/us/atin.mli new file mode 100644 index 0000000..3dfff82 --- /dev/null +++ b/lib/us/atin.mli @@ -0,0 +1,22 @@ +(* +ATIN (U.S. Adoption Taxpayer Identification Number). + +An Adoption Taxpayer Identification Number (ATIN) is a temporary +nine-digit number issued by the United States IRS for a child for whom the +adopting parents cannot obtain a Social Security Number. +*) + +exception Invalid_format + +val atin_re : Str.regexp +(** Regular expression for matching ATINs *) + +val validate : string -> string +(** Check if the number is a valid ATIN. + This checks the length and formatting if it is present. *) + +val is_valid : string -> bool +(** Check if the number is a valid ATIN. *) + +val format_number : string -> string +(** Reformat the number to the standard presentation format. *) diff --git a/lib/us/dune b/lib/us/dune new file mode 100644 index 0000000..784f967 --- /dev/null +++ b/lib/us/dune @@ -0,0 +1,4 @@ +(library + (name us) + (modules atin) + (libraries tools)) diff --git a/test/us/dune b/test/us/dune new file mode 100644 index 0000000..49c8cb3 --- /dev/null +++ b/test/us/dune @@ -0,0 +1,4 @@ +(test + (name test_atin) + (libraries alcotest us) + (modules test_atin)) diff --git a/test/us/test_atin.ml b/test/us/test_atin.ml new file mode 100644 index 0000000..5d5b53b --- /dev/null +++ b/test/us/test_atin.ml @@ -0,0 +1,24 @@ +let test_validate () = + let input = "900-93-0000" in + let expected_result = "900-93-0000" in + let result = Us.Atin.validate input in + Alcotest.(check string) "test_validate" expected_result result + +let test_is_valid () = + let input = "900-93-0000" in + let expected_result = true in + let result = Us.Atin.is_valid input in + Alcotest.(check bool) "test_is_valid" expected_result result + +let test_is_not_valid () = + Alcotest.check_raises "Invalid Length" Us.Atin.Invalid_format (fun () -> + ignore (Us.Atin.is_valid "123")) + +let suite = + [ + ("test_validate", `Quick, test_validate) + ; ("test_is_valid", `Quick, test_is_valid) + ; ("test_is_not_valid", `Quick, test_is_not_valid) + ] + +let () = Alcotest.run "ATIN" [ ("suite", suite) ]