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.
276 lines
8.9 KiB
276 lines
8.9 KiB
// |
|
// TimeChunk.swift |
|
// DateTools |
|
// |
|
// Created by Grayson Webster on 8/19/16. |
|
// Copyright © 2016 Grayson Webster. All rights reserved. |
|
// |
|
|
|
import Foundation |
|
|
|
/** |
|
* TimeChunk represents an abstract collection of `DateComponent`s intended for use in date manipulation. A `TimeChunk` differs from a |
|
* TimeInterval in that the former depends on the `Calendar` class (and takes into account daylight savings, leap year, etc.) while the |
|
* latter depends on hard, second based adjustments that are independent from calendar constructs. |
|
* |
|
* In essence, TimeChunk is meant to be a thin, more flexible layer over the `Calender` and `DateComponent` classes for ease of use. |
|
* `TimeChunk`s may be created either by calling the provided initializer or shorthand like `2.days`. TimeChunks are manipulable and combine |
|
* using basic arithmetic operators like + and -. |
|
* |
|
* For more information about the utility of TimeChunks in relation to Dates, see the `Date+Manipulations` class. |
|
*/ |
|
public struct TimeChunk { |
|
// MARK: - Variables |
|
|
|
public var seconds = 0 |
|
public var minutes = 0 |
|
public var hours = 0 |
|
public var days = 0 |
|
public var weeks = 0 |
|
public var months = 0 |
|
public var years = 0 |
|
|
|
public init() {} |
|
|
|
public init(seconds: Int, minutes: Int, hours: Int, days: Int, weeks: Int, months: Int, years: Int) { |
|
self.seconds = seconds |
|
self.minutes = minutes |
|
self.hours = hours |
|
self.days = days |
|
self.weeks = weeks |
|
self.months = months |
|
self.years = years |
|
} |
|
|
|
// MARK: - Comparisons |
|
|
|
/** |
|
* Check if two `TimeChunk`s are equal. |
|
* |
|
* - parameter chunk: `TimeChunk` to compare with self |
|
* |
|
* - returns: If all components in both `TimeChunk`s are equal |
|
*/ |
|
public func equals(chunk: TimeChunk) -> Bool { |
|
return (seconds == chunk.seconds && minutes == chunk.minutes && hours == chunk.hours && days == chunk.days && weeks == chunk.weeks && months == chunk.months && years == chunk.years) |
|
} |
|
|
|
// MARK: - Conversion |
|
|
|
/** |
|
* Generic conversion method. Years are taken to mean |
|
* 365 days. This method should not be used for accurate |
|
* date operations. Ex. 456.days.to(.years) will return 1. |
|
* |
|
* ! Months are not supported for conversions. They are not a |
|
* well defined unit of time without the context of a calendar. ! |
|
*/ |
|
public func to(_ unit: TimeUnits) -> Int { |
|
if months != 0 { |
|
print("Months are not supported for conversion due to their uncertain number of days.") |
|
return 0 |
|
} |
|
if unit == .seconds { |
|
var total = seconds |
|
total += minutes * 60 |
|
total += hours * 60 * 60 |
|
total += days * 24 * 60 * 60 |
|
total += weeks * 7 * 24 * 60 * 60 |
|
total += years * 365 * 24 * 60 * 60 |
|
return total |
|
} else if unit == .minutes { |
|
var total = minutes |
|
total += seconds / 60 |
|
total += hours * 60 |
|
total += days * 24 * 60 |
|
total += weeks * 7 * 24 * 60 |
|
total += years * 365 * 24 * 60 |
|
return total |
|
} else if unit == .hours { |
|
var total = hours |
|
let secondsToMinutes = seconds / 60 |
|
total += (minutes + secondsToMinutes) / 60 |
|
total += days * 24 |
|
total += weeks * 7 * 24 |
|
total += years * 365 * 24 |
|
return total |
|
} else if unit == .days { |
|
var total = days |
|
let secondsToMinutes = seconds / 60 |
|
let minutesToHours = (minutes + secondsToMinutes) / 60 |
|
total += (hours + minutesToHours) / 24 |
|
total += weeks * 7 |
|
total += years * 365 |
|
return total |
|
} else if unit == .weeks { |
|
var total = weeks |
|
let secondsToMinutes = seconds / 60 |
|
let minutesToHours = (minutes + secondsToMinutes) / 60 |
|
let hoursToDays = (hours + minutesToHours) / 24 |
|
total += (days + hoursToDays) / 7 |
|
total += years * 52 |
|
return total |
|
} else if unit == .years { |
|
var total = years |
|
let secondsToMinutes = seconds / 60 |
|
let minutesToHours = (minutes + secondsToMinutes) / 60 |
|
let hoursToDays = (hours + minutesToHours) / 24 |
|
let weeksToDays = weeks * 7 |
|
total += (days + hoursToDays + weeksToDays) / 365 |
|
return total |
|
} |
|
return 0 |
|
} |
|
|
|
// MARK: - Date Creation |
|
|
|
/** |
|
* Returns the current date decreased by the amount in self |
|
*/ |
|
public var earlier: Date { |
|
return earlier(than: Date()) |
|
} |
|
|
|
/** |
|
* Returns the current date increased by the amount in self |
|
*/ |
|
public var later: Date { |
|
return later(than: Date()) |
|
} |
|
|
|
/** |
|
* Returns the given date decreased by the amount in self. |
|
* |
|
* - parameter date: The date to decrease |
|
* |
|
* - returns: A new date with components decreased according to the variables of self |
|
*/ |
|
public func earlier(than date: Date) -> Date { |
|
return date.subtract(self) |
|
} |
|
|
|
/** |
|
* Returns the given date increased by the amount in self. |
|
* |
|
* - parameter date: The date to increase |
|
* |
|
* - returns: A new date with components increased according to the variables of self |
|
*/ |
|
public func later(than date: Date) -> Date { |
|
return date.add(self) |
|
} |
|
|
|
// MARK: - Lengthen / Shorten |
|
|
|
// MARK: In Place |
|
|
|
/** |
|
* Increase the variables of self (`TimeChunk`) by the variables of the given `TimeChunk`. |
|
* |
|
* - parameter chunk: The `TimeChunk` to increase self by |
|
* |
|
* - returns: The `TimeChunk` with variables increased |
|
*/ |
|
public func lengthened(by chunk: TimeChunk) -> TimeChunk { |
|
var newChunk = TimeChunk() |
|
newChunk.seconds = seconds + chunk.seconds |
|
newChunk.minutes = minutes + chunk.minutes |
|
newChunk.hours = hours + chunk.hours |
|
newChunk.days = days + chunk.days |
|
newChunk.weeks = weeks + chunk.weeks |
|
newChunk.months = months + chunk.months |
|
newChunk.years = years + chunk.years |
|
|
|
return newChunk |
|
} |
|
|
|
/** |
|
* Decrease the variables of self (`TimeChunk`) by the variables of the given `TimeChunk`. |
|
* |
|
* - parameter chunk: The `TimeChunk` to decrease self by |
|
* |
|
* - returns: The `TimeChunk` with variables decreased |
|
*/ |
|
public func shortened(by chunk: TimeChunk) -> TimeChunk { |
|
var newChunk = TimeChunk() |
|
newChunk.seconds = seconds - chunk.seconds |
|
newChunk.minutes = minutes - chunk.minutes |
|
newChunk.hours = hours - chunk.hours |
|
newChunk.days = days - chunk.days |
|
newChunk.weeks = weeks - chunk.weeks |
|
newChunk.months = months - chunk.months |
|
newChunk.years = years - chunk.years |
|
|
|
return newChunk |
|
} |
|
|
|
// MARK: Mutation |
|
|
|
/** |
|
* In place, increase the variables of self (`TimeChunk`) by the variables of the given `TimeChunk`. |
|
* |
|
* - parameter chunk: The `TimeChunk` to increase self by |
|
*/ |
|
public mutating func lengthen(by chunk: TimeChunk) { |
|
seconds += chunk.seconds |
|
minutes += chunk.minutes |
|
hours += chunk.hours |
|
days += chunk.days |
|
weeks += chunk.weeks |
|
months += chunk.months |
|
years += chunk.years |
|
} |
|
|
|
/** |
|
* In place, decrease the variables of self (`TimeChunk`) by the variables of the given `TimeChunk`. |
|
* |
|
* - parameter chunk: The `TimeChunk` to decrease self by |
|
*/ |
|
public mutating func shorten(by chunk: TimeChunk) { |
|
seconds -= chunk.seconds |
|
minutes -= chunk.minutes |
|
hours -= chunk.hours |
|
days -= chunk.days |
|
weeks -= chunk.weeks |
|
months -= chunk.months |
|
years -= chunk.years |
|
} |
|
|
|
// MARK: - Operator Overloads |
|
|
|
/** |
|
* Operator overload for adding two `TimeChunk`s |
|
*/ |
|
public static func + (leftAddend: TimeChunk, rightAddend: TimeChunk) -> TimeChunk { |
|
return leftAddend.lengthened(by: rightAddend) |
|
} |
|
|
|
/** |
|
* Operator overload for subtracting two `TimeChunk`s |
|
*/ |
|
public static func - (minuend: TimeChunk, subtrahend: TimeChunk) -> TimeChunk { |
|
return minuend.shortened(by: subtrahend) |
|
} |
|
|
|
/** |
|
* Operator overload for checking if two `TimeChunk`s are equal |
|
*/ |
|
public static func == (left: TimeChunk, right: TimeChunk) -> Bool { |
|
return left.equals(chunk: right) |
|
} |
|
|
|
/** |
|
* Operator overload for inverting (negating all variables) a `TimeChunk` |
|
*/ |
|
public static prefix func - (chunk: TimeChunk) -> TimeChunk { |
|
var invertedChunk = chunk |
|
invertedChunk.seconds = -chunk.seconds |
|
invertedChunk.minutes = -chunk.minutes |
|
invertedChunk.hours = -chunk.hours |
|
invertedChunk.days = -chunk.days |
|
invertedChunk.weeks = -chunk.weeks |
|
invertedChunk.months = -chunk.months |
|
invertedChunk.years = -chunk.years |
|
return invertedChunk |
|
} |
|
}
|
|
|