4

I would like to take a string like "My String 2022-01-07" extract the date part into a named capture.

I've tried the following regex, but it only works when there's an exact match:

# Does not work
iex> Regex.named_captures(~r/(?<date>\$?(\d{4}-\d{2}-\d{2})?)/, "My String 2021-01-01")
%{"date" => ""}

# Works
iex> Regex.named_captures(~r/(?<date>\$?(\d{4}-\d{2}-\d{2})?)/, "2021-01-01")
%{"date" => "2021-01-01"}

I've also tried this without luck:

iex> Regex.named_captures(~r/([a-zA-Z0-9 ]+?)(?<date>\$?(\d{4}-\d{2}-\d{2})?)/, "My String 2021-01-01")
%{"date" => ""}

Is there a way to use named captures to extract the date part of a string when you don't care about the characters surrounding the date?

I think I'm looking for a regex that will work like this:

iex> Regex.named_captures(REGEX???, "My String 2021-01-01 Other Parts")
%{"date" => "2021-01-01"}
Peter Brown
  • 50,956
  • 18
  • 113
  • 146

2 Answers2

3

You want

Regex.named_captures(~r/(?<date>\$?\d{4}-\d{2}-\d{2})/, "My String 2021-01-01")

Your regex - (?<date>\$?(\d{4}-\d{2}-\d{2})?) - represents a named capturing group with date as a name and a \$?(\d{4}-\d{2}-\d{2})? as a pattern. The \$?(\d{4}-\d{2}-\d{2})? pattern matches

  • \$? - an optional $ char
  • (\d{4}-\d{2}-\d{2})? - an optional sequence of four digits, -, two digits, -, two digits.

Since the pattern is not anchored (does not have to match the whole string) and both consecutive pattern parts are optional and thus can match an empty string, the ~r/(?<date>\$?(\d{4}-\d{2}-\d{2})?)/ regex **matches the first empty location (empty string) at the start of the "My String 2021-01-01" string.

Rule of thumb: If you do not want to match an empty string, make sure your pattern contains obligatory patterns, that must match at least one char.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 1
    Thanks a ton! I just realized the optional $ char shouldn't have even been in there in the first place and was a copy/paste from another regex I was working on. – Peter Brown Jan 07 '22 at 23:38
-1

Extract Date only:

void main() {

String inputString = "Your String 1/19/2023 9:29:11 AM";
  RegExp dateRegex = new RegExp(r"(\d{1,2}\/\d{1,2}\/\d{4})");
  Iterable<RegExpMatch> matches = dateRegex.allMatches(inputString);
  for (RegExpMatch m in matches) {
    print(m.group(0));
  }
}

This will output: 1/19/2023

Extract Date and time:

void main() {

String inputString = "Your String 1/19/2023 9:29:11 AM";
  RegExp dateTimeRegex = new RegExp(r"(\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}:\d{2} [AP]M)");
  Iterable<RegExpMatch> matches = dateTimeRegex.allMatches(inputString);
  for (RegExpMatch m in matches) {
    print(m.group(0));
  }
}

This will output: 1/19/2023 9:29:11 AM