add all api to sort by month
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
//
|
||||
// SwiftDate
|
||||
// Parse, validate, manipulate, and display dates, time and timezones in Swift
|
||||
//
|
||||
// Created by Daniele Margutti
|
||||
// - Web: https://www.danielemargutti.com
|
||||
// - Twitter: https://twitter.com/danielemargutti
|
||||
// - Mail: hello@danielemargutti.com
|
||||
//
|
||||
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Time period chains serve as a tightly coupled set of time periods.
|
||||
/// They are always organized by start and end date, and have their own characteristics like
|
||||
/// a StartDate and EndDate that are extrapolated from the time periods within.
|
||||
/// Time period chains do not allow overlaps within their set of time periods.
|
||||
/// This type of group is ideal for modeling schedules like sequential meetings or appointments.
|
||||
open class TimePeriodChain: TimePeriodGroup {
|
||||
|
||||
// MARK: - Chain Existence Manipulation
|
||||
|
||||
/**
|
||||
* Append a TimePeriodProtocol to the periods array and update the Chain's
|
||||
* beginning and end.
|
||||
*
|
||||
* - parameter period: TimePeriodProtocol to add to the collection
|
||||
*/
|
||||
public func append(_ period: TimePeriodProtocol) {
|
||||
let beginning = (periods.count > 0) ? periods.last!.end! : period.start
|
||||
|
||||
let newPeriod = TimePeriod(start: beginning!, duration: period.duration)
|
||||
periods.append(newPeriod)
|
||||
|
||||
//Update updateExtremes
|
||||
if periods.count == 1 {
|
||||
start = period.start
|
||||
end = period.end
|
||||
} else {
|
||||
end = end?.addingTimeInterval(period.duration)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a TimePeriodProtocol array to the periods array and update the Chain's
|
||||
* beginning and end.
|
||||
*
|
||||
* - parameter periodArray: TimePeriodProtocol list to add to the collection
|
||||
*/
|
||||
public func append<G: TimePeriodGroup>(contentsOf group: G) {
|
||||
for period in group.periods {
|
||||
let beginning = (periods.count > 0) ? periods.last!.end! : period.start
|
||||
|
||||
let newPeriod = TimePeriod(start: beginning!, duration: period.duration)
|
||||
periods.append(newPeriod)
|
||||
|
||||
//Update updateExtremes
|
||||
if periods.count == 1 {
|
||||
start = period.start
|
||||
end = period.end
|
||||
} else {
|
||||
end = end?.addingTimeInterval(period.duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert period into periods array at given index.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - period: The period to insert
|
||||
/// - index: Index to insert period at
|
||||
public func insert(_ period: TimePeriodProtocol, at index: Int) {
|
||||
//Check for special zero case which takes the beginning date
|
||||
if index == 0 && period.start != nil && period.end != nil {
|
||||
//Insert new period
|
||||
periods.insert(period, at: index)
|
||||
} else if period.start != nil && period.end != nil {
|
||||
//Insert new period
|
||||
periods.insert(period, at: index)
|
||||
} else {
|
||||
print("All TimePeriods in a TimePeriodChain must contain a defined start and end date")
|
||||
return
|
||||
}
|
||||
|
||||
//Shift all periods after inserted period
|
||||
for i in 0..<periods.count {
|
||||
if i > index && i > 0 {
|
||||
let currentPeriod = TimePeriod(start: period.start, end: period.end)
|
||||
periods[i].start = periods[i - 1].end
|
||||
periods[i].end = periods[i].start!.addingTimeInterval(currentPeriod.duration)
|
||||
}
|
||||
}
|
||||
|
||||
updateExtremes()
|
||||
}
|
||||
|
||||
/// Remove from period array at the given index.
|
||||
///
|
||||
/// - Parameter index: The index in the collection to remove
|
||||
public func remove(at index: Int) {
|
||||
//Retrieve duration of period to be removed
|
||||
let duration = periods[index].duration
|
||||
|
||||
//Remove period
|
||||
periods.remove(at: index)
|
||||
|
||||
//Shift all periods after inserted period
|
||||
for i in index..<periods.count {
|
||||
periods[i].shift(by: -duration)
|
||||
}
|
||||
updateExtremes()
|
||||
}
|
||||
|
||||
/// Remove all periods from period array.
|
||||
public func removeAll() {
|
||||
periods.removeAll()
|
||||
updateExtremes()
|
||||
}
|
||||
|
||||
// MARK: - Chain Content Manipulation
|
||||
|
||||
/// In place, shifts all chain time periods by a given time interval
|
||||
///
|
||||
/// - Parameter duration: The time interval to shift the period by
|
||||
public func shift(by duration: TimeInterval) {
|
||||
for var period in periods {
|
||||
period.shift(by: duration)
|
||||
}
|
||||
start = start?.addingTimeInterval(duration)
|
||||
end = end?.addingTimeInterval(duration)
|
||||
}
|
||||
|
||||
public override func map<T>(_ transform: (TimePeriodProtocol) throws -> T) rethrows -> [T] {
|
||||
return try periods.map(transform)
|
||||
}
|
||||
|
||||
public override func filter(_ isIncluded: (TimePeriodProtocol) throws -> Bool) rethrows -> [TimePeriodProtocol] {
|
||||
return try periods.filter(isIncluded)
|
||||
}
|
||||
|
||||
internal override func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, TimePeriodProtocol) throws -> Result) rethrows -> Result {
|
||||
return try periods.reduce(initialResult, nextPartialResult)
|
||||
}
|
||||
|
||||
/// Removes the last object from the `TimePeriodChain` and returns it
|
||||
public func pop() -> TimePeriodProtocol? {
|
||||
let period = periods.popLast()
|
||||
updateExtremes()
|
||||
|
||||
return period
|
||||
}
|
||||
|
||||
internal func updateExtremes() {
|
||||
start = periods.first?.start
|
||||
end = periods.last?.end
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user