Last active
July 3, 2019 11:28
-
-
Save christianselig/d0d4e3398da07c423db973406e8b9378 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
import Foundation | |
extension String { | |
/// Converts an ISO 8601 formatted `String` into `NSDateComponents`. | |
/// | |
/// - Note: Does not accept fractional input (e.g.: P3.5Y), must be integers (e.g.: P3Y6M). | |
/// - SeeAlso: https://en.wikipedia.org/wiki/ISO_8601#Durations | |
/// - Returns: If valid ISO 8601, an `NSDateComponents` representation, otherwise `nil`. | |
func ISO8601DateComponents() -> NSDateComponents? { | |
// Regex adapted from Moment.js https://github.com/moment/moment/blame/develop/src/lib/duration/create.js#L16 | |
let pattern = "^P(?:(\\d*)Y)?(?:(\\d*)M)?(?:(\\d*)W)?(?:(\\d*)D)?(?:T(?:(\\d*)H)?(?:(\\d*)M)?(?:(\\d*)S)?)?$" | |
let nsstringRepresentation = self as NSString | |
let regex = try! NSRegularExpression(pattern: pattern, options: [.anchorsMatchLines]) | |
guard let match = regex.firstMatch(in: self, options: [], range: NSRange(location: 0, length: nsstringRepresentation.length)) else { return nil } | |
let dateComponents = NSDateComponents() | |
if match.rangeAt(1).location != NSNotFound, let years = Int(nsstringRepresentation.substring(with: match.rangeAt(1)) as String) { | |
dateComponents.year = years | |
} | |
if match.rangeAt(2).location != NSNotFound, let month = Int(nsstringRepresentation.substring(with: match.rangeAt(2)) as String) { | |
dateComponents.month = month | |
} | |
if match.rangeAt(3).location != NSNotFound, let week = Int(nsstringRepresentation.substring(with: match.rangeAt(3)) as String) { | |
dateComponents.weekOfYear = week | |
} | |
if match.rangeAt(4).location != NSNotFound, let day = Int(nsstringRepresentation.substring(with: match.rangeAt(4)) as String) { | |
dateComponents.day = day | |
} | |
if match.rangeAt(5).location != NSNotFound, let hour = Int(nsstringRepresentation.substring(with: match.rangeAt(5)) as String) { | |
dateComponents.hour = hour | |
} | |
if match.rangeAt(6).location != NSNotFound, let minute = Int(nsstringRepresentation.substring(with: match.rangeAt(6)) as String) { | |
dateComponents.minute = minute | |
} | |
if match.rangeAt(7).location != NSNotFound, let second = Int(nsstringRepresentation.substring(with: match.rangeAt(7)) as String) { | |
dateComponents.second = second | |
} | |
return dateComponents | |
} | |
} |
Hi, does ISO8601DateFormatter support duration? I was not able to use ISO8601DateFormatter to convert duration
I tried and it sadly doesn't seem like it supports duration.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Works great for the YouTube API, FYI. It's quite performant.
Note if you're on iOS 10 or higher, Apple added
ISO8601DateFormatter
, but I needed iOS 9 support.