For the upcoming app I’m working on I need a way to easily detect dates the user may have typed at the end of a line. It was time to re-visit old faithful regex.
After lots of readings and tests I ended up settling on this beauty:
“.*[0-9]{2}/[0-9]{2}”
Here’s what it does:
The first section means take any character from the beginning of a line:
. Any character except new line
* Zero or more charecters
provided it ends in the second part…
[0-9]{2} Two numbers between 0 to 9
/ This specific seperator
[0-9]{2} Two numbers between 0 to 9
So in essence, it will take any line that ends in xx/xx where xx is any combination of two digits. That’s it, clear and simple!
***
Now, all we have to do is expand the number of cases to account for the user typing only one digit for the month or day.
Here’s a swift array containing each case: [“.*[0-9]{2}/[0-9]{2}”,”.*[0-9]{1}/[0-9]{2}”,”.*[0-9]{2}/[0-9]{1}”,”.*[0-9]{1}/[0-9]{1}”]
One thing I’d point out is that the order of the regex pattern matters, it should go from most complex to most simple as regex will stop once it finds a suitable match.
Here’s an example of all of it working together (in this case I’m also adding a year pattern):
func dateMatches(text: String) -> [String] {
let regexPatternMonth = [“.*[0-9]{2}/[0-9]{2}”,“.*[0-9]{1}/[0-9]{2}”,“.*[0-9]{2}/[0-9]{1}”,“.*[0-9]{1}/[0-9]{1}”]
let regexPatternYear = [“.*[0-9]{2}/[0-9]{2}/[0-9]{4}”,“.*[0-9]{1}/[0-9]{2}/[0-9]{4}”,“.*[0-9]{2}/[0-9]{1}/[0-9]{4}”,“.*[0-9]{1}/[0-9]{1}/[0-9]{4}”,“.*[0-9]{2}/[0-9]{2}/[0-9]{2}”,“.*[0-9]{1}/[0-9]{2}/[0-9]{2}”,“.*[0-9]{2}/[0-9]{1}/[0-9]{2}”,“.*[0-9]{1}/[0-9]{1}/[0-9]{2}”]
let regexPatternsToMatchArray = regexPatternMonth + regexPatternYear
do {
let regex = try NSRegularExpression(pattern: “(\(regexPatternsToMatchArray.joined(separator:“|”)))”)
let results = regex.matches(in: text,
range: NSRange(text.startIndex…, in: text))
let finalResult = results.map {
String(text[Range($0.range, in: text)!])
}
return finalResult
} catch let error {
print(“invalid regex: \(error.localizedDescription)“)
return []
}
}
That’s it, you can call this function and it will return the array of matching sub-strings.
From there you can process convert them into dates (make sure to account for localization as some countries use day/month and others month/day).
Hope this helps, if you’re new to regex here are some useful references: regex cheatsheet, validator, matching valid dates and ios regex.
Comments, questions I’m at @MarcMasVi on Twitter
Marc