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

//
// 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 {
Logger.info("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
}
}