date parser

This commit is contained in:
Ruidy 2022-02-03 15:18:36 -04:00
parent d3487aa841
commit 0ab1fcaa3e
11 changed files with 861 additions and 0 deletions

View file

@ -0,0 +1,22 @@
{
"blurb": "Learn about regular expressions by parsing dates.",
"authors": [
"neenjaw"
],
"contributors": [
"angelikatyborska",
"Cohen-Carlisle"
],
"files": {
"solution": [
"lib/date_parser.ex"
],
"test": [
"test/date_parser_test.exs"
],
"exemplar": [
".meta/exemplar.ex"
]
},
"language_versions": ">=1.10"
}

View file

@ -0,0 +1 @@
{"track":"elixir","exercise":"date-parser","id":"3f650e7a4dd641cc8e2c6abdbea38850","url":"https://exercism.org/tracks/elixir/exercises/date-parser","handle":"rjNemo","is_requester":true,"auto_approve":false}

View file

@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

24
date-parser/.gitignore vendored Normal file
View file

@ -0,0 +1,24 @@
# The directory Mix will write compiled artifacts to.
/_build/
# If you run "mix test --cover", coverage assets end up here.
/cover/
# The directory Mix downloads your dependencies sources to.
/deps/
# Where third-party dependencies like ExDoc output generated docs.
/doc/
# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch
# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
# Also ignore archive artifacts (built via "mix archive.build").
*.ez
# Ignore package tarball (built via "mix hex.build").
regular_expressions-*.tar

75
date-parser/HELP.md Normal file
View file

@ -0,0 +1,75 @@
# Help
## Running the tests
From the terminal, change to the base directory of the exercise then execute the tests with:
```bash
$ mix test
```
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
Documentation:
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
## Pending tests
In test suites of practice exercises, all but the first test have been tagged to be skipped.
Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol.
For example:
```elixir
# @tag :pending
test "shouting" do
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end
```
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
```bash
$ mix test --include pending
```
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
```elixir
# ExUnit.configure(exclude: :pending, trace: true)
```
## Useful `mix test` options
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
* `--failed` - runs only tests that failed the last time they ran
* `--max-failures` - the suite stops evaluating tests when this number of test failures
is reached
* `--seed 0` - disables randomization so the tests in a single file will always be ran
in the same order they were defined in
## Submitting your solution
You can submit your solution using the `exercism submit lib/date_parser.ex` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
If you can't find what you're looking for in the documentation, feel free to ask help in the Exercism's BEAM [gitter channel](https://gitter.im/exercism/xerlang).

52
date-parser/HINTS.md Normal file
View file

@ -0,0 +1,52 @@
# Hints
## General
- Review regular expression patterns from the introduction. Remember, when creating the pattern a string, you must escape some characters.
- Read about the [`Regex` module][regex-docs] in the documentation.
- Read about the [regular expression sigil][sigils-regex] in the Getting Started guide.
- Check out this website about regular expressions: [Regular-Expressions.info][website-regex-info].
- Check out this website about regular expressions: [Rex Egg -The world's most tyrannosauical regex tutorial][website-rexegg].
- Check out this website about regular expressions: [RegexOne - Learn Regular Expressions with simple, interactive exercises.][website-regexone].
- Check out this website about regular expressions: [Regular Expressions 101 - an online regex sandbox][website-regex-101].
- Check out this website about regular expressions: [RegExr - an online regex sandbox][website-regexr].
## 1. Match the day, month, and year from a date
- Remember to return a string representing the regular expression pattern.
- Review how to create _character classes_ or use _shorthand character classes_.
- Review _quantifiers_.
- A day is one or two digits.
- A month is one or two digits.
- A year is four digits.
## 2. Match the day of the week and the month of the year
- Review how to write a pattern to match _string literals_.
- Review _alternations_.
- Wrap the whole expression in a _group_.
## 3. Capture the day, month, and year
- Review how to write patterns for captures and named captures.
- Reuse the `day/0`, `month/0`, `year/0`, `day_names/0`, and `month_names/0` functions that you already implemented.
## 4. Combine the captures to capture the whole date
- Remember, string interpolation may be used to join strings.
- Reuse the `capture_day/0`, `capture_month/0`, `capture_year/0`, `capture_day_name/0`, and `capture_month_name/0` functions that you already implemented.
## 5. Narrow the capture to match only on the date
- Remembers, _anchors_ help to match the pattern to the **whole line**.
- String interpolation may be used in the regular expression sigil syntax.
- Reuse the `capture_numeric_date/0`, `capture_month_name_date/0`, and `capture_day_month_name_date/0` functions that you already implemented.
[regex-docs]: https://hexdocs.pm/elixir/Regex.html
[sigils-regex]: https://elixir-lang.org/getting-started/sigils.html#regular-expressions
[website-regex-info]: https://www.regular-expressions.info
[website-rexegg]: https://www.rexegg.com/
[website-regexone]: https://regexone.com/
[website-regex-101]: https://regex101.com/
[website-regexr]: https://regexr.com/
[website-regex-crossword]: https://regexcrossword.com/

196
date-parser/README.md Normal file
View file

@ -0,0 +1,196 @@
# Date Parser
Welcome to Date Parser on Exercism's Elixir Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
## Regular Expressions
Regular expressions (regex) are a powerful tool for working with strings in Elixir. Regular expressions in Elixir follow the **PCRE** specification (**P**erl **C**ompatible **R**egular **E**xpressions). String patterns representing the regular expression's meaning are first compiled then used for matching all or part of a string.
In Elixir, the most common way to create regular expressions is using the `~r` sigil. Sigils provide _syntactic sugar_ shortcuts for common tasks in Elixir. To match a _string literal_, we can use the string itself as a pattern following the sigil.
```elixir
~r/test/
```
The `=~/2` operator is useful to perform a regex match on a string to return a `boolean` result.
```elixir
"this is a test" =~ ~r/test/
# => true
```
Two notes about using sigils:
- many different delimiters may be used depending on your requirements rather than `/`
- string patterns are already _escaped_, when writing the pattern as a string not using a regex, you will have to _escape_ backslashes (`\`)
### Character classes
Matching a range of characters using square brackets `[]` defines a _character class_. This will match any one character to the characters in the class. You can also specify a range of characters like `a-z`, as long as the start and end represent a contiguous range of code points.
```elixir
regex = ~r/[a-z][ADKZ][0-9][!?]/
"jZ5!" =~ regex
# => true
"jB5?" =~ regex
# => false
```
_Shorthand character classes_ make the pattern more concise. For example:
- `\d` short for `[0-9]` (any digit)
- `\w` short for `[A-Za-z0-9_]` (any 'word' character)
- `\s` short for `[ \t\r\n\f]` (any whitespace character)
When a _shorthand character class_ is used outside of a sigil, it must be escaped: `"\\d"`
### Alternations
_Alternations_ use `|` as a special character to denote matching one _or_ another
```elixir
regex = ~r/cat|bat/
"bat" =~ regex
# => true
"cat" =~ regex
# => true
```
### Quantifiers
_Quantifiers_ allow for a repeating pattern in the regex. They affect the group preceding the quantifier.
- `{N, M}` where `N` is the minimum number of repetitions, and `M` is the maximum
- `{N,}` match `N` or more repetitions
- `{0,}` may also be written as `*`: match zero-or-more repetitions
- `{1,}` may also be written as `+`: match one-or-more repetitions
- `{,N}` match up to `N` repetitions
### Groups
Round brackets `()` are used to denote _groups_ and _captures_. The group may also be _captured_ in some instances to be returned for use. In Elixir, these may be named or un-named. Captures are named by appending `?<name>` after the opening parenthesis. Groups function as a single unit, like when followed by _quantifiers_.
```elixir
regex = ~r/(h)at/
Regex.replace(regex, "hat", "\\1op")
# => "hop"
regex = ~r/(?<letter_b>b)/
Regex.scan(regex, "blueberry", capture: :all_names)
# => [["b"], ["b"]]
```
### Anchors
_Anchors_ are used to tie the regular expression to the beginning or end of the string to be matched:
- `^` anchors to the beginning of the string
- `$` anchors to the end of the string
### Interpolation
Because the `~r` is a shortcut for `"pattern" |> Regex.escape() |> Regex.compile!()`, you may also use string interpolation to dynamically build a regular expression pattern:
```elixir
anchor = "$"
regex = ~r/end of the line#{anchor}/
"end of the line?" =~ regex
# => false
"end of the line" =~ regex
# => true
```
## Instructions
You have been tasked to write a service which ingests events. Each event has a date associated with it, but you notice that 3 different formats are being submitted to your service's endpoint:
- `"01/01/1970"`
- `"January 1, 1970"`
- `"Thursday, January 1, 1970"`
You can see there are some similarities between each of them, and decide to write some composable regular expression patterns.
## 1. Match the day, month, and year from a date
Implement `day/0`, `month/0`, and `year/0` to return a string pattern which, when compiled, would match the numeric components in `"01/01/1970"` (`dd/mm/yyyy`). The day and month may appear as `1` or `01` (left padded with zeroes).
```elixir
"31" =~ DateParser.day() |> Regex.compile!()
# => true
"12" =~ DateParser.month() |> Regex.compile!()
# => true
"1970" =~ DateParser.year() |> Regex.compile!()
# => true
```
## 2. Match the day of the week and the month of the year
Implement `day_names/0` and `month_names/0` to return a string pattern which, when compiled, would match the named day of the week and the named month of the year respectively.
```elixir
"Tuesday" =~ DateParser.day_names() |> Regex.compile!()
# => true
"June" =~ DateParser.month_names() |> Regex.compile!()
# => true
```
## 3. Capture the day, month, and year
Implement `capture_day/0`, `capture_month/0`, `capture_year/0`, `capture_day_name/0`, `capture_month_name/0` to return a string pattern which captures the respective components to the names: `"day"`, `"month"`, `"year"`, `"day_name"`, `"month_name"`
```elixir
DateParser.capture_month_name()
|> Regex.compile!()
|> Regex.named_captures("December")
# => %{"month_name" => "December"}
```
## 4. Combine the captures to capture the whole date
Implement `capture_numeric_date/0`, `capture_month_name_date()`, and `capture_day_month_name_date/0` to return a string pattern which captures the components from part 3 using the respective date format:
- numeric date - `"01/01/1970"`
- month name date - `"January 1, 1970"`
- day month name date - `"Thursday, January 1, 1970"`
```elixir
DateParser.capture_numeric_date()
|> Regex.compile!()
|> Regex.named_captures("01/01/1970")
# => %{"day" => "01", "month" => "01", "year" => "1970"}
```
## 5. Narrow the capture to match only on the date
Implement `match_numeric_date/0`, `match_month_name_date/0`, and `match_day_month_name_date/0` to return a compiled regular expression that only matches the date, and which can also capture the components.
```elixir
"Thursday, January 1, 1970 was the Unix epoch." =~ DateParser.match_day_month_name_date()
# => false
"Thursday, January 1, 1970" =~ DateParser.match_day_month_name_date()
# => true
DateParser.match_day_month_name_date()
|> Regex.named_captures("Thursday, January 1, 1970")
# => %{
# "day" => "1",
# "day_name" => "Thursday",
# "month_name" => "January",
# "year" => "1970"
# }
```
## Source
### Created by
- @neenjaw
### Contributed to by
- @angelikatyborska
- @Cohen-Carlisle

View file

@ -0,0 +1,34 @@
defmodule DateParser do
def day(), do: "\\d{1,2}"
def month(), do: "\\d{1,2}"
def year(), do: "\\d{4}"
def day_names(), do: "(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday)"
def month_names(),
do: "(January|February|March|April|May|June|July|August|September|October|November|December)"
def capture_day(), do: "(?<day>#{day()})"
def capture_month(), do: "(?<month>#{month()})"
def capture_year(), do: "(?<year>#{year()})"
def capture_day_name(), do: "(?<day_name>#{day_names()})"
def capture_month_name(), do: "(?<month_name>#{month_names()})"
def capture_numeric_date(), do: "#{capture_day()}/#{capture_month()}/#{capture_year()}"
def capture_month_name_date(), do: "#{capture_month_name()} #{capture_day()}, #{capture_year()}"
def capture_day_month_name_date(), do: "#{capture_day_name()}, #{capture_month_name_date()}"
def match_numeric_date(), do: ~r/^#{capture_numeric_date()}$/
def match_month_name_date(), do: ~r/^#{capture_month_name_date()}$/
def match_day_month_name_date(), do: ~r/^#{capture_day_month_name_date()}$/
end

28
date-parser/mix.exs Normal file
View file

@ -0,0 +1,28 @@
defmodule DateParser.MixProject do
use Mix.Project
def project do
[
app: :date_parser,
version: "0.1.0",
# elixir: "~> 1.10",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end

View file

@ -0,0 +1,423 @@
defmodule DateParserTest do
use ExUnit.Case
@tag task_id: 1
test "numeric pattern for day is a string" do
assert DateParser.day() |> is_binary()
end
describe "numeric pattern for day matches" do
@tag task_id: 1
test "un-padded days" do
assert "1" =~ Regex.compile!(DateParser.day())
assert "2" =~ Regex.compile!(DateParser.day())
assert "3" =~ Regex.compile!(DateParser.day())
assert "4" =~ Regex.compile!(DateParser.day())
assert "5" =~ Regex.compile!(DateParser.day())
assert "6" =~ Regex.compile!(DateParser.day())
assert "7" =~ Regex.compile!(DateParser.day())
assert "8" =~ Regex.compile!(DateParser.day())
assert "9" =~ Regex.compile!(DateParser.day())
assert "10" =~ Regex.compile!(DateParser.day())
assert "11" =~ Regex.compile!(DateParser.day())
assert "12" =~ Regex.compile!(DateParser.day())
assert "13" =~ Regex.compile!(DateParser.day())
assert "14" =~ Regex.compile!(DateParser.day())
assert "15" =~ Regex.compile!(DateParser.day())
assert "16" =~ Regex.compile!(DateParser.day())
assert "17" =~ Regex.compile!(DateParser.day())
assert "18" =~ Regex.compile!(DateParser.day())
assert "19" =~ Regex.compile!(DateParser.day())
assert "20" =~ Regex.compile!(DateParser.day())
assert "21" =~ Regex.compile!(DateParser.day())
assert "22" =~ Regex.compile!(DateParser.day())
assert "23" =~ Regex.compile!(DateParser.day())
assert "24" =~ Regex.compile!(DateParser.day())
assert "25" =~ Regex.compile!(DateParser.day())
assert "26" =~ Regex.compile!(DateParser.day())
assert "27" =~ Regex.compile!(DateParser.day())
assert "28" =~ Regex.compile!(DateParser.day())
assert "29" =~ Regex.compile!(DateParser.day())
assert "30" =~ Regex.compile!(DateParser.day())
assert "31" =~ Regex.compile!(DateParser.day())
end
@tag task_id: 1
test "padded days" do
assert "01" =~ Regex.compile!(DateParser.day())
assert "02" =~ Regex.compile!(DateParser.day())
assert "03" =~ Regex.compile!(DateParser.day())
assert "04" =~ Regex.compile!(DateParser.day())
assert "05" =~ Regex.compile!(DateParser.day())
assert "06" =~ Regex.compile!(DateParser.day())
assert "07" =~ Regex.compile!(DateParser.day())
assert "08" =~ Regex.compile!(DateParser.day())
assert "09" =~ Regex.compile!(DateParser.day())
end
end
describe "numeric pattern for day doesn't match" do
@tag task_id: 1
test "too few digits", do: refute("" =~ Regex.compile!("^#{DateParser.day()}$"))
@tag task_id: 1
test "too many digits", do: refute("111" =~ Regex.compile!("^#{DateParser.day()}$"))
@tag task_id: 1
test "one letter", do: refute("a" =~ Regex.compile!(DateParser.day()))
@tag task_id: 1
test "two letters", do: refute("bb" =~ Regex.compile!(DateParser.day()))
end
@tag task_id: 1
test "numeric pattern for month is a string" do
assert DateParser.month() |> is_binary()
end
describe "numeric pattern for month matches" do
@tag task_id: 1
test "un-padded months" do
assert "1" =~ Regex.compile!(DateParser.month())
assert "2" =~ Regex.compile!(DateParser.month())
assert "3" =~ Regex.compile!(DateParser.month())
assert "4" =~ Regex.compile!(DateParser.month())
assert "5" =~ Regex.compile!(DateParser.month())
assert "6" =~ Regex.compile!(DateParser.month())
assert "7" =~ Regex.compile!(DateParser.month())
assert "8" =~ Regex.compile!(DateParser.month())
assert "9" =~ Regex.compile!(DateParser.month())
assert "10" =~ Regex.compile!(DateParser.month())
assert "11" =~ Regex.compile!(DateParser.month())
assert "12" =~ Regex.compile!(DateParser.month())
end
@tag task_id: 1
test "padded months" do
assert "01" =~ Regex.compile!(DateParser.month())
assert "02" =~ Regex.compile!(DateParser.month())
assert "03" =~ Regex.compile!(DateParser.month())
assert "04" =~ Regex.compile!(DateParser.month())
assert "05" =~ Regex.compile!(DateParser.month())
assert "06" =~ Regex.compile!(DateParser.month())
assert "07" =~ Regex.compile!(DateParser.month())
assert "08" =~ Regex.compile!(DateParser.month())
assert "09" =~ Regex.compile!(DateParser.month())
end
end
describe "numeric pattern for month doesn't match" do
@tag task_id: 1
test "too few digits", do: refute("" =~ Regex.compile!("^#{DateParser.month()}$"))
@tag task_id: 1
test "too many digits", do: refute("111" =~ Regex.compile!("^#{DateParser.month()}$"))
@tag task_id: 1
test "one letter", do: refute("a" =~ Regex.compile!(DateParser.month()))
@tag task_id: 1
test "two letters", do: refute("bb" =~ Regex.compile!(DateParser.month()))
@tag task_id: 1
test "short month name", do: refute("Jan" =~ Regex.compile!(DateParser.month()))
@tag task_id: 1
test "long month name", do: refute("January" =~ Regex.compile!(DateParser.month()))
end
@tag task_id: 1
test "numeric pattern for year is a string" do
assert DateParser.year() |> is_binary()
end
describe "numeric pattern for year" do
@tag task_id: 1
test "matches 4 digits", do: assert("1970" =~ Regex.compile!("^#{DateParser.year()}$"))
@tag task_id: 1
test "doesn't match short year", do: refute("84" =~ Regex.compile!("^#{DateParser.year()}$"))
@tag task_id: 1
test "doesn't match letters", do: refute("198A" =~ Regex.compile!("^#{DateParser.year()}$"))
@tag task_id: 1
test "doesn't match too few", do: refute("198" =~ Regex.compile!("^#{DateParser.year()}$"))
@tag task_id: 1
test "doesn't match too many", do: refute("19701" =~ Regex.compile!("^#{DateParser.year()}$"))
end
@tag task_id: 2
test "pattern for day names is a string" do
assert DateParser.day_names() |> is_binary()
end
@tag task_id: 2
test "day names match" do
assert "Sunday" =~ Regex.compile!(DateParser.day_names())
assert "Monday" =~ Regex.compile!(DateParser.day_names())
assert "Tuesday" =~ Regex.compile!(DateParser.day_names())
assert "Wednesday" =~ Regex.compile!(DateParser.day_names())
assert "Thursday" =~ Regex.compile!(DateParser.day_names())
assert "Friday" =~ Regex.compile!(DateParser.day_names())
assert "Saturday" =~ Regex.compile!(DateParser.day_names())
end
@tag task_id: 2
test "day names don't match with trailing or leading whitespace" do
refute " Sunday " =~ Regex.compile!("^#{DateParser.day_names()}$")
refute " Monday " =~ Regex.compile!("^#{DateParser.day_names()}$")
refute " Tuesday " =~ Regex.compile!("^#{DateParser.day_names()}$")
refute " Wednesday " =~ Regex.compile!("^#{DateParser.day_names()}$")
refute " Thursday " =~ Regex.compile!("^#{DateParser.day_names()}$")
refute " Friday " =~ Regex.compile!("^#{DateParser.day_names()}$")
refute " Saturday " =~ Regex.compile!("^#{DateParser.day_names()}$")
end
describe "day names don't match" do
@tag task_id: 2
test "combined" do
refute "TuesdayWednesday" =~ Regex.compile!("^#{DateParser.day_names()}$")
end
@tag task_id: 2
test "short name" do
refute "Sun" =~ Regex.compile!("^#{DateParser.day_names()}$")
end
@tag task_id: 2
test "numeric day of the week (0-indexed)" do
refute "0" =~ Regex.compile!("^#{DateParser.day_names()}$")
end
@tag task_id: 2
test "numeric day of the week (1-indexed)" do
refute "1" =~ Regex.compile!("^#{DateParser.day_names()}$")
end
end
@tag task_id: 2
test "pattern for month names is a string" do
assert DateParser.month_names() |> is_binary()
end
@tag task_id: 2
test "month names match" do
assert "January" =~ Regex.compile!(DateParser.month_names())
assert "February" =~ Regex.compile!(DateParser.month_names())
assert "March" =~ Regex.compile!(DateParser.month_names())
assert "April" =~ Regex.compile!(DateParser.month_names())
assert "May" =~ Regex.compile!(DateParser.month_names())
assert "June" =~ Regex.compile!(DateParser.month_names())
assert "July" =~ Regex.compile!(DateParser.month_names())
assert "August" =~ Regex.compile!(DateParser.month_names())
assert "September" =~ Regex.compile!(DateParser.month_names())
assert "October" =~ Regex.compile!(DateParser.month_names())
assert "November" =~ Regex.compile!(DateParser.month_names())
assert "December" =~ Regex.compile!(DateParser.month_names())
end
@tag task_id: 2
test "month names don't match with trailing or leading whitespace" do
refute " January " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " February " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " March " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " April " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " May " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " June " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " July " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " August " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " September " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " October " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " November " =~ Regex.compile!("^#{DateParser.month_names()}$")
refute " December " =~ Regex.compile!("^#{DateParser.month_names()}$")
end
describe "month names don't match" do
@tag task_id: 2
test "combined" do
refute "JanuaryFebruary" =~ Regex.compile!("^#{DateParser.month_names()}$")
end
@tag task_id: 2
test "short name" do
refute "Jan" =~ Regex.compile!("^#{DateParser.month_names()}$")
end
@tag task_id: 2
test "numeric month of the year (0-indexed)" do
refute "0" =~ Regex.compile!("^#{DateParser.month_names()}$")
end
@tag task_id: 2
test "numeric month of the year (1-indexed)" do
refute "1" =~ Regex.compile!("^#{DateParser.month_names()}$")
end
end
describe "capture" do
@tag task_id: 3
test "numeric month" do
assert DateParser.capture_month() |> is_binary()
assert %{"month" => "01"} =
DateParser.capture_month()
|> Regex.compile!()
|> Regex.named_captures("01")
end
@tag task_id: 3
test "numeric day" do
assert DateParser.capture_day() |> is_binary()
assert %{"day" => "01"} =
DateParser.capture_day()
|> Regex.compile!()
|> Regex.named_captures("01")
end
@tag task_id: 3
test "numeric year" do
assert DateParser.capture_year() |> is_binary()
assert %{"year" => "1970"} =
DateParser.capture_year()
|> Regex.compile!()
|> Regex.named_captures("1970")
end
@tag task_id: 3
test "capture day name" do
assert DateParser.capture_day_name() |> is_binary()
assert %{"day_name" => "Monday"} =
DateParser.capture_day_name()
|> Regex.compile!()
|> Regex.named_captures("Monday")
end
@tag task_id: 3
test "capture month name" do
assert DateParser.capture_month_name() |> is_binary()
assert %{"month_name" => "February"} =
DateParser.capture_month_name()
|> Regex.compile!()
|> Regex.named_captures("February")
end
@tag task_id: 4
test "numeric date" do
assert DateParser.capture_numeric_date() |> is_binary()
assert %{"year" => "1970", "month" => "02", "day" => "01"} =
DateParser.capture_numeric_date()
|> Regex.compile!()
|> Regex.named_captures("01/02/1970")
end
@tag task_id: 4
test "month named date" do
assert DateParser.capture_month_name_date() |> is_binary()
assert %{"year" => "1970", "month_name" => "January", "day" => "1"} =
DateParser.capture_month_name_date()
|> Regex.compile!()
|> Regex.named_captures("January 1, 1970")
end
@tag task_id: 4
test "day and month named date" do
assert DateParser.capture_day_month_name_date() |> is_binary()
assert %{
"year" => "1970",
"month_name" => "January",
"day" => "1",
"day_name" => "Thursday"
} =
DateParser.capture_day_month_name_date()
|> Regex.compile!()
|> Regex.named_captures("Thursday, January 1, 1970")
end
end
describe "regex match" do
@tag task_id: 5
test "pattern to match numeric date is a regex" do
assert match?(%Regex{}, DateParser.match_numeric_date())
end
@tag task_id: 5
test "numeric date matches" do
assert DateParser.match_numeric_date() |> Regex.match?("01/02/1970")
end
@tag task_id: 5
test "numeric date has named captures" do
assert %{"year" => "1970", "month" => "02", "day" => "01"} =
DateParser.match_numeric_date()
|> Regex.named_captures("01/02/1970")
end
@tag task_id: 5
test "numeric date with a prefix doesn't match" do
refute DateParser.match_numeric_date() |> Regex.match?("The day was 01/02/1970")
end
@tag task_id: 5
test "numeric date with a suffix doesn't match" do
refute DateParser.match_numeric_date() |> Regex.match?("01/02/1970 was the day")
end
@tag task_id: 5
test "pattern to match month name date is a regex" do
assert match?(%Regex{}, DateParser.match_month_name_date())
end
@tag task_id: 5
test "month named date matches" do
assert DateParser.match_month_name_date() |> Regex.match?("January 1, 1970")
end
@tag task_id: 5
test "month named date has named captures" do
assert %{"year" => "1970", "month_name" => "January", "day" => "1"} =
DateParser.match_month_name_date()
|> Regex.named_captures("January 1, 1970")
end
@tag task_id: 5
test "month named date with a prefix doesn't match" do
refute DateParser.match_month_name_date() |> Regex.match?("The day was January 1, 1970")
end
@tag task_id: 5
test "month named date with a suffix doesn't match" do
refute DateParser.match_month_name_date() |> Regex.match?("January 1, 1970 was the day")
end
@tag task_id: 5
test "pattern to match day month name date is a regex" do
assert match?(%Regex{}, DateParser.match_day_month_name_date())
end
@tag task_id: 5
test "day and month names date matches" do
assert DateParser.match_day_month_name_date() |> Regex.match?("Thursday, January 1, 1970")
end
@tag task_id: 5
test "day and month names date has named captures" do
assert %{
"year" => "1970",
"month_name" => "January",
"day" => "1",
"day_name" => "Thursday"
} =
DateParser.match_day_month_name_date()
|> Regex.named_captures("Thursday, January 1, 1970")
end
@tag task_id: 5
test "day and month names date with a prefix doesn't match" do
refute DateParser.match_day_month_name_date()
|> Regex.match?("The day way Thursday, January 1, 1970")
end
@tag task_id: 5
test "day and month names date with a suffix doesn't match" do
refute DateParser.match_day_month_name_date()
|> Regex.match?("Thursday, January 1, 1970 was the day")
end
end
end

View file

@ -0,0 +1,2 @@
ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true, seed: 0)