You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.8 KiB
146 lines
4.8 KiB
// |
|
// TimePeriodGroup.swift |
|
// DateTools |
|
// |
|
// Created by Grayson Webster on 8/17/16. |
|
// Copyright © 2016 Grayson Webster. All rights reserved. |
|
// |
|
|
|
import Foundation |
|
|
|
/** |
|
* Time period groups are the final abstraction of date and time in DateTools. Here, time |
|
* periods are gathered and organized into something useful. There are two main types of time |
|
* period groups, `TimePeriodCollection` and `TimePeriodChain`. |
|
* |
|
* [Visit our github page](https://github.com/MatthewYork/DateTools#time-period-groups) for more information. |
|
*/ |
|
open class TimePeriodGroup: Sequence { |
|
// MARK: - Variables |
|
|
|
/** |
|
* The array of periods that define the group. |
|
*/ |
|
internal var periods: [TimePeriodProtocol] = [] |
|
|
|
internal var _beginning: Date? |
|
internal var _end: Date? |
|
|
|
/** |
|
* The earliest beginning date of a `TimePeriod` in the group. |
|
* Nil if any `TimePeriod` in group has a nil beginning date (indefinite). |
|
* (Read Only) |
|
*/ |
|
public var beginning: Date? { |
|
return _beginning |
|
} |
|
|
|
/** |
|
* The latest end date of a `TimePeriod` in the group. |
|
* Nil if any `TimePeriod` in group has a nil end date (indefinite). |
|
* (Read Only) |
|
*/ |
|
public var end: Date? { |
|
return _end |
|
} |
|
|
|
/** |
|
* The number of periods in the periods array. |
|
*/ |
|
public var count: Int { |
|
return periods.count |
|
} |
|
|
|
/** |
|
* The total amount of time between the earliest and latest dates stored in the |
|
* periods array. Nil if any beginning or end date in any contained period is nil. |
|
*/ |
|
public var duration: TimeInterval? { |
|
if beginning != nil, end != nil { |
|
return end!.timeIntervalSince(beginning!) |
|
} |
|
return nil |
|
} |
|
|
|
// MARK: - Initializers |
|
|
|
public init() {} |
|
|
|
// MARK: - Comparisons |
|
|
|
/** |
|
* If `self.periods` contains the exact elements as the given group's periods array. |
|
* |
|
* - parameter group: The group to compare to self |
|
* |
|
* - returns: True if the periods arrays are the same |
|
*/ |
|
public func equals(_ group: TimePeriodGroup) -> Bool { |
|
return containSameElements(array1: periods, group.periods) |
|
} |
|
|
|
// MARK: - Sequence Protocol |
|
|
|
public func makeIterator() -> IndexingIterator<[TimePeriodProtocol]> { |
|
return periods.makeIterator() |
|
} |
|
|
|
public func map<T>(_ transform: (TimePeriodProtocol) throws -> T) rethrows -> [T] { |
|
return try periods.map(transform) |
|
} |
|
|
|
public func filter(_ isIncluded: (TimePeriodProtocol) throws -> Bool) rethrows -> [TimePeriodProtocol] { |
|
return try periods.filter(isIncluded) |
|
} |
|
|
|
public func forEach(_ body: (TimePeriodProtocol) throws -> Void) rethrows { |
|
return try periods.forEach(body) |
|
} |
|
|
|
public func split(maxSplits: Int, omittingEmptySubsequences: Bool, whereSeparator isSeparator: (TimePeriodProtocol) throws -> Bool) rethrows -> [AnySequence<TimePeriodProtocol>] { |
|
return try periods.split(maxSplits: maxSplits, omittingEmptySubsequences: omittingEmptySubsequences, whereSeparator: isSeparator).map(AnySequence.init) |
|
} |
|
|
|
subscript(index: Int) -> TimePeriodProtocol { |
|
return periods[index] |
|
} |
|
|
|
internal func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, TimePeriodProtocol) throws -> Result) rethrows -> Result { |
|
return try periods.reduce(initialResult, nextPartialResult) |
|
} |
|
|
|
internal func containSameElements(array1: [TimePeriodProtocol], _ array2: [TimePeriodProtocol]) -> Bool { |
|
guard array1.count == array2.count else { |
|
return false // No need to sorting if they already have different counts |
|
} |
|
|
|
var compArray1: [TimePeriodProtocol] = array1.sorted { (period1: TimePeriodProtocol, period2: TimePeriodProtocol) -> Bool in |
|
if period1.beginning == nil, period2.beginning == nil { |
|
return false |
|
} else if period1.beginning == nil { |
|
return true |
|
} else if period2.beginning == nil { |
|
return false |
|
} else { |
|
return period2.beginning! < period1.beginning! |
|
} |
|
} |
|
var compArray2: [TimePeriodProtocol] = array2.sorted { (period1: TimePeriodProtocol, period2: TimePeriodProtocol) -> Bool in |
|
if period1.beginning == nil, period2.beginning == nil { |
|
return false |
|
} else if period1.beginning == nil { |
|
return true |
|
} else if period2.beginning == nil { |
|
return false |
|
} else { |
|
return period2.beginning! < period1.beginning! |
|
} |
|
} |
|
for x in 0 ..< compArray1.count { |
|
if !compArray1[x].equals(compArray2[x]) { |
|
return false |
|
} |
|
} |
|
return true |
|
} |
|
}
|
|
|