diff --git a/README.md b/README.md index fe5706a61..c11607a77 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,10 @@ It currently consists of # Release Notes BOAT is still under development and subject to change. +## 0.17.46 +* boat-scaffold + * Enhanced ISO8601 Date Formatting with Fractional Seconds Support for Swift template. + * The `OpenISO8601DateFormatter` template now supports parsing and formatting ISO8601 dates with none, one, or multiple fractional seconds in Swift 5. This enhancement provides greater flexibility and precision when working with date and time values, accommodating various use cases that require different levels of fractional second accuracy. ## 0.17.36 * Lint rule `B014` doesn't throw a null exception when parsing a string array property in a schema. ## 0.17.35 diff --git a/boat-scaffold/src/main/templates/boat-swift5/OpenISO8601DateFormatter.mustache b/boat-scaffold/src/main/templates/boat-swift5/OpenISO8601DateFormatter.mustache index b7974abcb..2b68feffe 100644 --- a/boat-scaffold/src/main/templates/boat-swift5/OpenISO8601DateFormatter.mustache +++ b/boat-scaffold/src/main/templates/boat-swift5/OpenISO8601DateFormatter.mustache @@ -18,6 +18,15 @@ import Foundation return formatter }() + // Primary formatter with fractional seconds + private static let sharedDateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + return formatter + }() + private func setup() { calendar = Calendar(identifier: .iso8601) locale = Locale(identifier: "en_US_POSIX") @@ -39,6 +48,33 @@ import Foundation if let result = super.date(from: string) { return result } - return OpenISO8601DateFormatter.withoutSeconds.date(from: string) + if let result = OpenISO8601DateFormatter.withoutSeconds.date(from: string) { + return result + } + return OpenISO8601DateFormatter.parseDate(from: string) + } + + private static func parseDate(from dateString: String) -> Date? { + // Base date format + let baseFormat = "yyyy-MM-dd'T'HH:mm:ss" + + // Create an instance of DateFormatter for parsing + let dateFormatter = OpenISO8601DateFormatter.sharedDateFormatter + + // Check for fractional seconds by locating the dot + guard let dotIndex = dateString.firstIndex(of: ".") else { + // No fractional seconds, use base format + dateFormatter.dateFormat = baseFormat + return dateFormatter.date(from: dateString) + } + + // Extract fractional part length + let fractionLength = dateString[dateString.index(after: dotIndex)...].count + + // Construct the date format with fractional seconds + let fractionalFormat = String(repeating: "S", count: fractionLength) + dateFormatter.dateFormat = "\(baseFormat).\(fractionalFormat)" + + return dateFormatter.date(from: dateString) } -} \ No newline at end of file +}