Skip to content

Instantly share code, notes, and snippets.

@beccadax
Last active March 30, 2016 05:47
Show Gist options
  • Save beccadax/4272a3e01ed7037d2c5d6ba413ecf2a9 to your computer and use it in GitHub Desktop.
Save beccadax/4272a3e01ed7037d2c5d6ba413ecf2a9 to your computer and use it in GitHub Desktop.
Second design for striding over dates
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