Last active
March 30, 2016 05:47
-
-
Save beccadax/4272a3e01ed7037d2c5d6ba413ecf2a9 to your computer and use it in GitHub Desktop.
Second design for striding over dates
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 NSCalendar { | |
public enum Interval { | |
case zero | |
case other(n: Int, calendar: NSCalendar, unit: NSCalendarUnit, options: NSCalendarOptions) | |
init(n: Int, calendar: NSCalendar, unit: NSCalendarUnit, options: NSCalendarOptions) { | |
if n == 0 { | |
self = .zero | |
} | |
else { | |
self = .other(n: n, calendar: calendar, unit: unit, options: options) | |
} | |
} | |
var _fields: (UInt, Int, UInt, UInt) { | |
switch self { | |
case .zero: | |
return (0, 0, 0, 0) | |
case let .other (n, calendar, unit, options): | |
return (unit.rawValue, n, ObjectIdentifier(calendar).uintValue, options.rawValue) | |
} | |
} | |
} | |
public func interval(n: Int, _ unit: NSCalendarUnit, options: NSCalendarOptions = [.MatchNextTimePreservingSmallerUnits]) -> Interval { | |
return Interval(n: n, calendar: self, unit: unit, options: options) | |
} | |
} | |
public prefix func - (stride: NSCalendar.Interval) -> NSCalendar.Interval { | |
switch stride { | |
case .zero: | |
return .zero | |
case let .other(n, calendar, unit, options): | |
return NSCalendar.Interval(n: -n, calendar: calendar, unit: unit, options: options) | |
} | |
} | |
public func - (lhs: NSCalendar.Interval, rhs: NSCalendar.Interval) -> NSCalendar.Interval { | |
switch (lhs, rhs) { | |
case (let value, .zero): | |
return value | |
case (.zero, let value): | |
return -value | |
case let (.other (n, calendar, unit, options), .other (rightN, rCalendar, rUnit, rOptions)) where (calendar, unit, options) == (rCalendar, rUnit, rOptions): | |
return .other(n: n - rightN, calendar: calendar, unit: unit, options: options) | |
default: | |
fatalError("Mismatched strides") | |
} | |
} | |
public func < (lhs: NSCalendar.Interval, rhs: NSCalendar.Interval) -> Bool { | |
return lhs._fields < rhs._fields | |
} | |
public func == (lhs: NSCalendar.Interval, rhs: NSCalendar.Interval) -> Bool { | |
return lhs._fields == rhs._fields | |
} | |
extension NSCalendar.Interval: SignedNumberType { | |
public init(integerLiteral value: Int) { | |
guard value == 0 else { | |
fatalError("integerLiteral not implemented except for 0") | |
} | |
self = .zero | |
} | |
} | |
public func < (lhs: NSDate, rhs: NSDate) -> Bool { | |
return lhs.compare(rhs) == .OrderedAscending | |
} | |
extension NSDate: Strideable { | |
public func distanceTo(other: NSDate) -> NSCalendar.Interval { | |
fatalError("distanceTo not implemented") | |
} | |
public func advancedBy(distance: NSCalendar.Interval) -> Self { | |
switch distance { | |
case .zero: | |
return self | |
case let .other(n, calendar, unit, options): | |
let date = calendar.dateByAddingUnit(unit, value: n, toDate: self, options: options)! | |
// I'm not convinced this is actually safe... | |
return self.dynamicType.init(timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate) | |
} | |
} | |
} | |
let calendar = NSCalendar.currentCalendar() | |
let now = NSDate() | |
let tomorrow = now + calendar.interval(1, .Day) | |
let yesterday = now - calendar.interval(1, .Day) | |
for date in yesterday.stride(through: tomorrow, by: calendar.interval(1, .Day)) { | |
print(date) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment