Skip to content

Instantly share code, notes, and snippets.

@Busta117
Created October 24, 2016 05:49
Show Gist options
  • Save Busta117/a453cf3cbf64a43252a82b7168a1652c to your computer and use it in GitHub Desktop.
Save Busta117/a453cf3cbf64a43252a82b7168a1652c to your computer and use it in GitHub Desktop.
return the right dateString and dateFormat of a ISO8601 to use it in DateFormatter, validated by regular expression, so, you don't need to fight again with those formats
func formatFrom(_ value:String) -> (dateString:String?, dateFormat:String?) {
var regexString = "\\A(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})" // Mandatory - YYYY-MM-DDTHH:mm
regexString = regexString + ":?(\\d{2})?" // Optional - :ss
regexString = regexString + "[.]?(\\d{1,6})?" // Optional - .nnnnnn
regexString = regexString + "([+-])?(\\d{2})?:?(\\d{2})?|Z" // Optional -[+-]hh:mm or Z
regexString = regexString + "\\z"
let regex: NSRegularExpression?
var matchesResult: [NSTextCheckingResult]?
do{
regex = try NSRegularExpression (pattern: regexString, options: NSRegularExpression.Options.caseInsensitive)
matchesResult = regex!.matches(in:value, options: NSRegularExpression.MatchingOptions.reportCompletion, range:NSMakeRange(0, value.characters.count))
} catch{
return (nil, nil)
}
guard let matches = matchesResult, matches.count > 0 else {
return (nil, nil)
}
var YYYY: String?, MM: String?, DD: String?, hh: String?, mm: String?, ss: String?, nn: String?, sign: String?, Zhh: String?, Zmm: String?
var tempRange: NSRange!
//this function is to convert a NSRange to Range<String.Index>
let convertRange:(_ nsRange: NSRange, _ text:String) -> Range<String.Index>? = { nsRange, text in
guard
let from16 = text.utf16.index(text.utf16.startIndex, offsetBy: nsRange.location, limitedBy: text.utf16.endIndex),
let to16 = text.utf16.index(from16, offsetBy: nsRange.length, limitedBy: text.utf16.endIndex),
let from = String.Index(from16, within: text),
let to = String.Index(to16, within: text)
else { return nil }
return from ..< to
}
for match in matches {
let matchRange = match.range
let matchCount = match.numberOfRanges - 1
var idx = 0 //components start from 1, 0 is the complete string
let checkAndAssign:()->(String?) = {
if idx < matchCount {
idx = idx + 1
tempRange = match.rangeAt(idx)
var substring:String? = tempRange.location != NSNotFound ? value.substring(with: convertRange(tempRange, value)!) : nil
return substring
}
return nil
}
YYYY = checkAndAssign()
MM = checkAndAssign()
DD = checkAndAssign()
hh = checkAndAssign()
mm = checkAndAssign()
ss = checkAndAssign()
nn = checkAndAssign()
sign = checkAndAssign()
Zhh = checkAndAssign()
Zmm = checkAndAssign()
}
var dateString:String = ""
var formatString:String = ""
if let YYYY = YYYY {
dateString = dateString + YYYY + "-"
formatString = formatString + "yyyy" + "-"
}
if let MM = MM {
dateString = dateString + MM + "-"
formatString = formatString + "MM" + "-"
}
if let DD = DD {
dateString = dateString + DD
formatString = formatString + "dd"
}
if let hh = hh {
dateString = dateString + "T" + hh
formatString = formatString + "'T'" + "HH"
}
if let mm = mm {
dateString = dateString + ":" + mm
formatString = formatString + ":" + "mm"
}
if let ss = ss {
dateString = dateString + ":" + ss
formatString = formatString + ":" + "ss"
}
if let nn = nn {
dateString = dateString + "." + nn
formatString = formatString + "." + String(repeating: "S", count: nn.characters.count)
}
if let sign = sign {
dateString = dateString + sign
formatString = formatString + "Z"
}
if let Zhh = Zhh {
dateString = dateString + Zhh
formatString = formatString + "ZZ"
}
if let Zmm = Zmm {
dateString = dateString + Zmm
formatString = formatString + "ZZ"
}
return (dateString, formatString)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment