Skip to content

Commit

Permalink
support rdate
Browse files Browse the repository at this point in the history
  • Loading branch information
hongxinhope committed Apr 14, 2016
1 parent aceea6d commit 53a0922
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 17 deletions.
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ recurrenceRule.byweekday = ...
recurrenceRule.byhour = ...
recurrenceRule.byminute = ...
recurrenceRule.bysecond = ...
recurrenceRule.rdate = ...
recurrenceRule.exdate = ...
```

Expand All @@ -47,8 +48,20 @@ print(ruleString)
// RRULE:FREQ=MONTHLY;DTSTART=20160404T021000Z;COUNT=5;INTERVAL=2;WKST=MO;BYDAY=MO,TU
```

##### Exclusion date
##### Inclusion date and Exclusion date
```swift
let rdateString = "RDATE:20180706T160000Z,20210706T160000Z"
if let inclusionDate = InclusionDate(rdateString: rdateString) {
print(inclusionDate.toRDateString())
// RDATE:20180706T160000Z,20210706T160000Z

print(inclusionDate.dates)
/*
2018-07-07 00:00:00 Sun
2021-07-07 00:00:00 Sun
*/
}

let exdateString = "EXDATE:20181231T160000Z,20201231T160000Z"
if let exclusionDate = ExclusionDate(exdateString: exdateString, unitGranularity: .Year) {
print(exclusionDate.toExDateString())
Expand All @@ -67,13 +80,15 @@ if let exclusionDate = ExclusionDate(exdateString: exdateString, unitGranularity
let ruleString = "RRULE:FREQ=YEARLY;COUNT=11;WKST=MO"
if let rule = RecurrenceRule(recurrenceWithRRuleString: ruleString) {
var rule = rule
rule.rdate = inclusionDate // RDATE:20180706T160000Z,20210706T160000Z
rule.exdate = exclusionDate // EXDATE:20181231T160000Z,20201231T160000Z
let allDates = rule.allOccurrences()
print(allDates)
/*
2016-04-14 14:22:30 Thu
2017-04-14 14:22:30 Fri
2018-04-14 14:22:30 Sat
2018-07-07 00:00:00 Sat
2020-04-14 14:22:30 Tue
2022-04-14 14:22:30 Thu
2023-04-14 14:22:30 Fri
Expand All @@ -82,12 +97,13 @@ if let rule = RecurrenceRule(recurrenceWithRRuleString: ruleString) {
2026-04-14 14:22:30 Tue
*/

let date = dateFormatter.dateFromString("2017-01-01 00:00:00 Sun")
let otherDate = dateFormatter.dateFromString("2020-01-01 00:00:00 Wed")
let date = dateFormatter.dateFromString("2018-01-01 00:00:00 Sun")
let otherDate = dateFormatter.dateFromString("2024-01-01 00:00:00 Mon")
let betweenDates = rule.occurrencesBetween(date: date!, andDate: otherDate!)
print(betweenDates)
/*
2018-04-14 14:22:30 Sat
2018-07-07 00:00:00 Sat
2020-04-14 14:22:30 Tue
2022-04-14 14:22:30 Thu
2023-04-14 14:22:30 Fri
Expand Down
4 changes: 4 additions & 0 deletions RRuleSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
D31B13BF1CAA7F1800D0B863 /* Generators.swift in Sources */ = {isa = PBXBuildFile; fileRef = D31B13BE1CAA7F1700D0B863 /* Generators.swift */; };
D382675C1CB4BCFB0080C91A /* NSDate+Comparison.swift in Sources */ = {isa = PBXBuildFile; fileRef = D382675B1CB4BCFB0080C91A /* NSDate+Comparison.swift */; };
D393D72F1CBF507700B89FB8 /* ExclusionDate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D393D72E1CBF507700B89FB8 /* ExclusionDate.swift */; };
D393D7311CBF79C800B89FB8 /* InclusionDate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D393D7301CBF79C800B89FB8 /* InclusionDate.swift */; };
D3D7E3E51CB3E03F00BF052F /* nlp.js in Resources */ = {isa = PBXBuildFile; fileRef = D3D7E3E31CB3E03F00BF052F /* nlp.js */; };
D3D7E3E61CB3E03F00BF052F /* rrule.js in Resources */ = {isa = PBXBuildFile; fileRef = D3D7E3E41CB3E03F00BF052F /* rrule.js */; };
D3D7E3E81CB3EBC800BF052F /* JavaScriptBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3D7E3E71CB3EBC800BF052F /* JavaScriptBridge.swift */; };
Expand All @@ -29,6 +30,7 @@
D31B13BE1CAA7F1700D0B863 /* Generators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Generators.swift; sourceTree = "<group>"; };
D382675B1CB4BCFB0080C91A /* NSDate+Comparison.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSDate+Comparison.swift"; sourceTree = "<group>"; };
D393D72E1CBF507700B89FB8 /* ExclusionDate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExclusionDate.swift; sourceTree = "<group>"; };
D393D7301CBF79C800B89FB8 /* InclusionDate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InclusionDate.swift; sourceTree = "<group>"; };
D3D7E3E31CB3E03F00BF052F /* nlp.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = nlp.js; sourceTree = "<group>"; };
D3D7E3E41CB3E03F00BF052F /* rrule.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = rrule.js; sourceTree = "<group>"; };
D3D7E3E71CB3EBC800BF052F /* JavaScriptBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JavaScriptBridge.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -67,6 +69,7 @@
children = (
D3D7E3E21CB3E03F00BF052F /* lib */,
D31B13AD1CA90A9A00D0B863 /* RecurrenceRule.swift */,
D393D7301CBF79C800B89FB8 /* InclusionDate.swift */,
D393D72E1CBF507700B89FB8 /* ExclusionDate.swift */,
D31B13A91CA8F37F00D0B863 /* RRule.swift */,
D31B13BE1CAA7F1700D0B863 /* Generators.swift */,
Expand Down Expand Up @@ -180,6 +183,7 @@
D382675C1CB4BCFB0080C91A /* NSDate+Comparison.swift in Sources */,
D31B13AE1CA90A9A00D0B863 /* RecurrenceRule.swift in Sources */,
D3D7E3E81CB3EBC800BF052F /* JavaScriptBridge.swift in Sources */,
D393D7311CBF79C800B89FB8 /* InclusionDate.swift in Sources */,
D31B13B01CA90ED300D0B863 /* RecurrenceFrequency.swift in Sources */,
D393D72F1CBF507700B89FB8 /* ExclusionDate.swift in Sources */,
D31B13BF1CAA7F1800D0B863 /* Generators.swift in Sources */,
Expand Down
12 changes: 10 additions & 2 deletions RRuleSwift/Generators.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public extension RecurrenceRule {
}

var occurrences = allOccurrences
if let rdates = rdate?.dates {
occurrences.appendContentsOf(rdates)
}

if let exdates = exdate?.dates, unit = exdate?.unit {
for occurrence in occurrences {
for exdate in exdates {
Expand All @@ -43,7 +47,7 @@ public extension RecurrenceRule {
}
}

return occurrences
return occurrences.sort { $0.isBeforeOrSameWith($1) }
}

public func occurrencesBetween(date date: NSDate, andDate otherDate: NSDate) -> [NSDate] {
Expand All @@ -68,6 +72,10 @@ public extension RecurrenceRule {
}

var occurrences = betweenOccurrences
if let rdates = rdate?.dates {
occurrences.appendContentsOf(rdates)
}

if let exdates = exdate?.dates, unit = exdate?.unit {
for occurrence in occurrences {
for exdate in exdates {
Expand All @@ -80,6 +88,6 @@ public extension RecurrenceRule {
}
}

return occurrences
return occurrences.sort { $0.isBeforeOrSameWith($1) }
}
}
53 changes: 53 additions & 0 deletions RRuleSwift/InclusionDate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// InclusionDate.swift
// RRuleSwift
//
// Created by Xin Hong on 16/3/28.
// Copyright © 2016年 Teambition. All rights reserved.
//

import Foundation

public struct InclusionDate {
/// All inclusive dates.
public private(set) var dates = [NSDate]()

public init(dates: [NSDate]) {
self.dates = dates
}

public init?(rdateString string: String) {
let string = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
guard let range = string.rangeOfString("RDATE:") where range.startIndex == string.startIndex else {
print("error: invalid rdate string, must be started with 'RDATE:'")
return nil
}
let rdateString = string.substringFromIndex(range.endIndex)
let rdates = rdateString.componentsSeparatedByString(",").flatMap { (dateString) -> String? in
if (dateString.isEmpty || dateString.characters.count == 0) {
return nil
}
return dateString
}

self.dates = rdates.flatMap({ (dateString) -> NSDate? in
return RRule.dateFormatter.dateFromString(dateString)
})
}

public func toRDateString() -> String {
var rdateString = "RDATE:"
let dateStrings = dates.map { (date) -> String in
return RRule.dateFormatter.stringFromDate(date)
}
if dateStrings.count > 0 {
rdateString += dateStrings.joinWithSeparator(",")
}

if rdateString.substringFromIndex(rdateString.endIndex.advancedBy(-1)) == "," {
rdateString.removeAtIndex(rdateString.endIndex.advancedBy(-1))
}

return rdateString
}
}
5 changes: 4 additions & 1 deletion RRuleSwift/RecurrenceRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ public struct RecurrenceRule {
/// The seconds of the minute associated with the recurrence rule, as an array of integers.
public var bysecond = [Int]()

/// The exclusion dates of the recurrence rule.
/// The inclusive dates of the recurrence rule.
public var rdate: InclusionDate?

/// The exclusion dates of the recurrence rule. The dates of this property will not be generated, even if some inclusive rdate matches the recurrence rule.
public var exdate: ExclusionDate?

public init(frequency: RecurrenceFrequency) {
Expand Down
2 changes: 1 addition & 1 deletion RRuleSwift/Supporting Files/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.0.5</string>
<string>0.0.6</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
4 changes: 2 additions & 2 deletions RRuleSwiftExample/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.0.5</string>
<string>0.0.6</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>5</string>
<string>6</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
Expand Down
13 changes: 12 additions & 1 deletion RRuleSwiftExample/RRuleExample.playground/Contents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,21 @@ if let rule1 = RecurrenceRule(recurrenceWithRRuleString: ruleString1) {
})
}

let rdateString = "RDATE:20160701T023000Z,20120702T023000Z"
if let inclusionDate = InclusionDate(rdateString: rdateString) {
let rdates = inclusionDate.dates
}

let exdateString = "EXDATE:20160416T030000Z,20160420T030000Z"
if let exclusionDate = ExclusionDate(exdateString: exdateString, unitGranularity: .Day) {
let exdates = exclusionDate.dates
}

let rdate1 = dateFormatter.dateFromString("2018-07-07 00:00:00 Sun")!
let rdate2 = dateFormatter.dateFromString("2021-07-07 00:00:00 Sun")!
let ruleInclusionDate = InclusionDate(dates: [rdate1, rdate2])
let ruleRDateString = ruleInclusionDate.toRDateString()

let exdate1 = dateFormatter.dateFromString("2019-01-01 00:00:00 Sun")!
let exdate2 = dateFormatter.dateFromString("2021-01-01 00:00:00 Wed")!
let ruleExclusionDate = ExclusionDate(dates: [exdate1, exdate2], unitGranularity: .Year)
Expand All @@ -34,12 +44,13 @@ let ruleString2 = "RRULE:FREQ=YEARLY;COUNT=11;WKST=MO"
if let rule2 = RecurrenceRule(recurrenceWithRRuleString: ruleString2) {
var rule2 = rule2
rule2.exdate = ruleExclusionDate
rule2.rdate = ruleInclusionDate
let allDates = rule2.allOccurrences().map({ (date) -> String in
return dateFormatter.stringFromDate(date)
})

let date = dateFormatter.dateFromString("2018-01-01 00:00:00 Sun")
let otherDate = dateFormatter.dateFromString("2024-01-01 00:00:00 Wed")
let otherDate = dateFormatter.dateFromString("2024-01-01 00:00:00 Mon")
let betweenDates = rule2.occurrencesBetween(date: date!, andDate: otherDate!).map({ (date) -> String in
return dateFormatter.stringFromDate(date)
})
Expand Down
26 changes: 19 additions & 7 deletions RRuleSwiftExample/RRuleExample.playground/timeline.xctimeline
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
version = "3.0">
<TimelineItems>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=5&amp;CharacterRangeLoc=1349&amp;EndingColumnNumber=14&amp;EndingLineNumber=36&amp;StartingColumnNumber=9&amp;StartingLineNumber=36&amp;Timestamp=482305742.591149"
documentLocation = "#CharacterRangeLen=5&amp;CharacterRangeLoc=1810&amp;EndingColumnNumber=14&amp;EndingLineNumber=47&amp;StartingColumnNumber=9&amp;StartingLineNumber=47&amp;Timestamp=482312964.24219"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=1346&amp;EndingColumnNumber=17&amp;EndingLineNumber=36&amp;StartingColumnNumber=9&amp;StartingLineNumber=36&amp;Timestamp=482305742.59131"
lockedSize = "{334, 216}"
documentLocation = "#CharacterRangeLen=8&amp;CharacterRangeLoc=1807&amp;EndingColumnNumber=17&amp;EndingLineNumber=47&amp;StartingColumnNumber=9&amp;StartingLineNumber=47&amp;Timestamp=482312964.242376"
lockedSize = "{334, 251}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=12&amp;CharacterRangeLoc=1619&amp;EndingColumnNumber=21&amp;EndingLineNumber=42&amp;StartingColumnNumber=9&amp;StartingLineNumber=42&amp;Timestamp=482305742.591435"
documentLocation = "#CharacterRangeLen=12&amp;CharacterRangeLoc=2080&amp;EndingColumnNumber=21&amp;EndingLineNumber=53&amp;StartingColumnNumber=9&amp;StartingLineNumber=53&amp;Timestamp=482314267.49539"
lockedSize = "{295, 168}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
Expand All @@ -26,21 +26,33 @@
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=1&amp;CharacterRangeLoc=856&amp;EndingColumnNumber=31&amp;EndingLineNumber=23&amp;StartingColumnNumber=5&amp;StartingLineNumber=23&amp;Timestamp=482304339.187826"
documentLocation = "#CharacterRangeLen=1&amp;CharacterRangeLoc=1021&amp;EndingColumnNumber=31&amp;EndingLineNumber=28&amp;StartingColumnNumber=5&amp;StartingLineNumber=28&amp;Timestamp=482312338.140483"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=7&amp;CharacterRangeLoc=828&amp;EndingColumnNumber=16&amp;EndingLineNumber=23&amp;StartingColumnNumber=9&amp;StartingLineNumber=23&amp;Timestamp=482304339.187957"
documentLocation = "#CharacterRangeLen=7&amp;CharacterRangeLoc=993&amp;EndingColumnNumber=16&amp;EndingLineNumber=28&amp;StartingColumnNumber=9&amp;StartingLineNumber=28&amp;Timestamp=482312338.140614"
lockedSize = "{236, 71}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=16&amp;CharacterRangeLoc=1096&amp;EndingColumnNumber=21&amp;EndingLineNumber=29&amp;StartingColumnNumber=5&amp;StartingLineNumber=29&amp;Timestamp=482305742.591905"
documentLocation = "#CharacterRangeLen=16&amp;CharacterRangeLoc=1521&amp;EndingColumnNumber=21&amp;EndingLineNumber=39&amp;StartingColumnNumber=5&amp;StartingLineNumber=39&amp;Timestamp=482312518.66394"
lockedSize = "{321.5, 50}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=15&amp;CharacterRangeLoc=1233&amp;EndingColumnNumber=20&amp;EndingLineNumber=34&amp;StartingColumnNumber=5&amp;StartingLineNumber=34&amp;Timestamp=482312518.664078"
lockedSize = "{323, 50}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
<LoggerValueHistoryTimelineItem
documentLocation = "#CharacterRangeLen=6&amp;CharacterRangeLoc=801&amp;EndingColumnNumber=15&amp;EndingLineNumber=23&amp;StartingColumnNumber=9&amp;StartingLineNumber=23&amp;Timestamp=482312519.413657"
lockedSize = "{227, 71}"
selectedRepresentationIndex = "0"
shouldTrackSuperviewWidth = "NO">
</LoggerValueHistoryTimelineItem>
</TimelineItems>
</Timeline>

0 comments on commit 53a0922

Please sign in to comment.