Reputation: 813
So it is pretty straight forward code. I have an input date that I want to validate against a specific format (the input date should perfectly match the date format specified), so I used the following code, input an invalid date (that should failed matching) but to my surprise it matches the date format and returns a valid date
import Foundation
let inputValue = "12/10/199" // Returns valid date even for "12/10.199"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"
if let dateOfBirth = dateFormatter.date(from: inputValue) {
print("Valid date \(dateOfBirth)") // Prints Valid date. Why?
}
else {
print("Invalid date")
}
Console output
Valid date 0199-10-11 18:06:32 +0000
Upvotes: 0
Views: 856
Reputation: 285082
According to Unicode Date Format Patterns only the two digit year format yy
checks also for the length, 3 y
and more add leading zeros up to the number of y
.
My suggestion is to validate the string format with Regular Expression (the whole string must be 2 digits followed by a slash followed by two digits followed by a slash followed by 4 digits) and to use the new DateParseStrategy
API introduced in iOS 15 / macOS 12 which is more comprehensible than the abstract string date format pattern.
let inputValue = "12/10/199"
let strategy = Date.ParseStrategy(format: "\(day: .twoDigits)/\(month: .twoDigits)/\(year: .defaultDigits)",
timeZone: .current)
if let _ = inputValue.range(of: #"^\d{2}/\d{2}/\d{4}$"#, options: .regularExpression),
let dateOfBirth = try? Date(inputValue, strategy: strategy) {
print("Valid date \(dateOfBirth)")
}
else {
print("Invalid date")
}
In iOS 16 / macOS 10.13 the regex validation will be included in ParseStrategy.
Upvotes: 1
Reputation: 344
Do not mistake the string you use as format of the date formatter for a regular expression. This would have also worked if the parsed string used the “-“ as separator between the date components.
Upvotes: 0