Instantly share code, notes, and snippets.

Embed
What would you like to do?
extension DateFormatter
{
private enum DateFormats: String
{
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
{
if let foundDate = parse(dateString, using: DateFormats.basicDate)
{
return foundDate
}
else if let foundDate = parse(dateString, using: DateFormats.basicDateWithTime_With_Miliseconds)
{
return foundDate
}
else if let foundDate = parse(dateString, using: DateFormats.basicDateWithTime_Without_Miliseconds)
{
return foundDate
}
else if let foundDate = parse(dateString, using: DateFormats.basicDateWithTime_WithX_Miliseconds)
{
return foundDate
}
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