From dce464ce195def62374fc8272edd64e9a0e517a7 Mon Sep 17 00:00:00 2001 From: Dan Loewenherz Date: Sat, 16 Sep 2023 08:33:02 -0500 Subject: [PATCH] backport updates --- .../DateFormatter+LionheartExtensions.swift | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Pod/Classes/Core/DateFormatter+LionheartExtensions.swift b/Pod/Classes/Core/DateFormatter+LionheartExtensions.swift index 1154647..bc45ac1 100644 --- a/Pod/Classes/Core/DateFormatter+LionheartExtensions.swift +++ b/Pod/Classes/Core/DateFormatter+LionheartExtensions.swift @@ -22,7 +22,7 @@ fileprivate struct DateFormatterString { static let DateComponent4 = "yyyy-dd-MM" static let DateComponent5 = "yyyyMMddHHmmssZ" static let DateComponent6 = "MMMM d, yyyy" - + static let TimeComponent1 = "HH:mm" static let TimeComponent2 = "hh:mm a" static let TimeComponent3 = "HH:mm:ss" @@ -31,10 +31,10 @@ fileprivate struct DateFormatterString { static let TimeComponent6 = "hh:mm:ss a Z" static let TimeComponent7 = "HH:mm:ssZ" static let TimeComponent8 = "HH:mm:ss.SSSZ" - + // Take one of the following static let NoSpaceFormatStrings = [DateComponent1, DateComponent2, DateComponent3, DateComponent4, DateComponent5] - + // And mix with one of these static let OneSpaceFormatStrings = [TimeComponent1, TimeComponent3, TimeComponent7, TimeComponent8] static let TwoSpaceFormatStrings = [TimeComponent2, TimeComponent4, TimeComponent5] @@ -45,21 +45,25 @@ public extension DateFormatter { private convenience init(format: String) { self.init() locale = Locale(identifier: "en_US_POSIX") + + // Without setting the timezone and locale, dates like "2023-03-12T02:10:00" will fail to parse. + // 2am on March 12 is not a valid time! + timeZone = TimeZone(secondsFromGMT: 0) dateFormat = format } - + /// Returns a `DateFormatter` that handles all of the provided `dateStrings`, or `nil` if a formatter could not be found. static func formatter(dateStrings: [String]) throws -> DateFormatter { var numberOfSpaces: Int? for dateString in dateStrings { let characters: [Character] = dateString.filter({ $0 == " " || $0 == "T" }) let count = characters.count - + // If the number of spaces between date strings is inconsistent, there's no way we can find a formatter to match all of them. if let numberOfSpaces = numberOfSpaces, count != numberOfSpaces { throw DateFormatError.emptyDates } - + numberOfSpaces = count } @@ -67,7 +71,7 @@ public extension DateFormatter { guard let _numberOfSpaces = numberOfSpaces else { throw DateFormatError.unspecified } - + var formatters: [DateFormatter] = [] if _numberOfSpaces == 0 { formatters = DateFormatterString.NoSpaceFormatStrings.map { DateFormatter(format: $0) } @@ -78,19 +82,21 @@ public extension DateFormatter { case 2: timeFormatStrings = DateFormatterString.TwoSpaceFormatStrings formatters.append(DateFormatter(format: DateFormatterString.DateComponent6)) - + case 3: timeFormatStrings = DateFormatterString.ThreeSpaceFormatStrings default: throw DateFormatError.noMatchingFormat } - + for dateString in DateFormatterString.NoSpaceFormatStrings { + formatters.append(DateFormatter(format: dateString)) + for timeString in timeFormatStrings { formatters.append(DateFormatter(format: "\(dateString) \(timeString)")) formatters.append(DateFormatter(format: "\(dateString)'T'\(timeString)")) } } } - + formatterLoop: for formatter in formatters { for dateString in dateStrings { guard formatter.date(from: dateString) != nil else { @@ -98,11 +104,11 @@ public extension DateFormatter { continue formatterLoop } } - + // If we got here, all of the strings worked with this formatter. return formatter } - + // No date formatter worked for everything. Fail. throw DateFormatError.noMatchingFormat }