This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension DateFormatter | |
{ | |
private enum DateFormats: String, CaseIterable { | |
case basicDate = "yyyy-MM-dd" | |
case basicDateWithTime_Without_Miliseconds = "yyyy-MM-dd HH:mm:ss" | |
case basicDateWithTime_With_Miliseconds = "yyyy-MM-dd HH:mm:ss.SSSSS" | |
case basicDateWithTime_WithX_Miliseconds = "yyyy-MM-dd HH:mm:ss.SSSSx" | |
var withTimeStamp: String { | |
switch self { | |
case .basicDate : return "yyyy-MM-dd" | |
case .basicDateWithTime_Without_Miliseconds : return "yyyy-MM-dd'T'HH:mm:ss" | |
case .basicDateWithTime_With_Miliseconds : return "yyyy-MM-dd'T'HH:mm:ss.SSSSS" | |
case .basicDateWithTime_WithX_Miliseconds : return "yyyy-MM-dd'T'HH:mm:ss.SSSSx" | |
} | |
} | |
} | |
// MARK: Public method | |
/* We start with an empty state for dateFormat, once we found a format the works | |
we use it all the time to save time, otherwise we try other formats. */ | |
func parseDate(from string: String?) -> Date { | |
guard let dateString = string else { return Date() } | |
if let date = self.date(from: dateString) { | |
return date | |
} | |
else { | |
return locateCorrectFormat(for: dateString) | |
} | |
} | |
// MARK: Private methods | |
private func locateCorrectFormat(for dateString: String) -> Date { | |
for dateFormat in DateFormats.allCases { | |
if let date = parse(dateString, using: dateFormat) { | |
return date | |
} | |
} | |
return useRegexToExtractDate(from: dateString) | |
} | |
private func parse(_ string: String, using dateFormat: DateFormats) -> Date? { | |
self.dateFormat = dateFormat.rawValue | |
if let date = self.date(from: string) { | |
return date | |
} | |
self.dateFormat = dateFormat.withTimeStamp | |
if let date = self.date(from: string) { | |
return date | |
} | |
return nil | |
} | |
private func useRegexToExtractDate(from stringFromAPI: String) -> Date { | |
// (----year---)[-/.](---month-----)[-/.](---------day----------) | |
let basicDatePattern = "(19|20)\\d\\d[-/.](0[1-9]|1[012])[-/.](0[1-9]|[12][0-9]|3[01])" | |
if let regex = try? NSRegularExpression(pattern: basicDatePattern, options: NSRegularExpression.Options(rawValue: 0)) { | |
if let textCheckingResault = regex.firstMatch(in: stringFromAPI, | |
options: .reportCompletion, | |
range: NSRange(location: 0, length: (stringFromAPI.count))) | |
{ | |
let croppedDate = (stringFromAPI as NSString).substring(with: textCheckingResault.range) | |
let croppedDateMatchingBasicFormat = replacCharectersInStringToMatchBasicDateFormat(croppedDate) | |
if let foundDate = parse(croppedDateMatchingBasicFormat, using: DateFormats.basicDate) { | |
return foundDate | |
} | |
} | |
} | |
return Date() | |
} | |
private func replacCharectersInStringToMatchBasicDateFormat(_ croppedDate: String) -> String { | |
let croppedDateSeperatedByHyphen = String(croppedDate.map { char in | |
if char == "." || char == "/" { | |
return "-" | |
} | |
return char | |
}) | |
return croppedDateSeperatedByHyphen | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment