Created
February 7, 2018 18:26
-
-
Save acrookston/fdb7da75bf6a1b0935eae89ecef10c28 to your computer and use it in GitHub Desktop.
Swift Date helpers
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
// | |
// CoreExtensions | |
// | |
// Created by Andrew Crookston on 1/30/18. | |
// | |
import Foundation | |
public extension DateComponents { | |
public static func with(year: Int? = nil, month: Int? = nil, day: Int? = nil, hour: Int? = nil, minute: Int? = nil, second: Int? = nil, calendar: Calendar = .current, timeZone: TimeZone? = nil) -> DateComponents { | |
var components = DateComponents() | |
components.year = year | |
components.month = month | |
components.day = day | |
components.hour = hour | |
components.minute = minute | |
components.second = second | |
components.calendar = calendar | |
components.timeZone = timeZone ?? calendar.timeZone | |
return components | |
} | |
/// Return date object using provided calendar or Calendar.current | |
var date: Date? { | |
return (calendar ?? Calendar.current).date(from: self) | |
} | |
} | |
public extension Date { | |
/// Creates a date from the specified components. | |
/// | |
/// Returns: A new Date, or nil if a date could not be found in `calendar` matching the components. | |
/// | |
public init?(year: Int, month: Int, day: Int, hour: Int? = nil, minute: Int? = nil, second: Int? = nil, timeZone: TimeZone? = nil, calendar: Calendar = .current) { | |
let components = DateComponents.with(year: year, month: month, day: day, hour: hour, minute: minute, second: second, calendar: calendar, timeZone: timeZone) | |
guard let date = calendar.date(from: components) else { return nil } | |
self = date | |
} | |
/// Convert Date to DateComponents selecting only specified units; such as `.year`, `.month`, or `.day`. | |
/// | |
public func dateComponents(_ units: Set<Calendar.Component>, calendar: Calendar = .current) -> DateComponents { | |
return calendar.dateComponents(units, from: self) | |
} | |
/// Beginning of day is interepreted as 00:00:00. | |
/// Returns: A new Date at beginning of `self`'s day according to calendar timezone | |
public func beginningOfDay(_ calendar: Calendar = .current) -> Date? { | |
return calendar.date(from: dateComponents([.year, .month, .day])) | |
} | |
// MARK: - Confirmations / Validations | |
/// End of day is interepreted as 23:59:59 (nanoseconds currently ignored). | |
/// Returns: A new Date at end of `self`'s day according to calendar timezone. | |
public func endOfDay(_ calendar: Calendar = .current) -> Date? { | |
guard let beginning = beginningOfDay() else { return nil } | |
return calendar.date(byAdding: DateComponents(calendar: calendar, day: 1, second: -1), to: beginning) | |
} | |
public func sameDayAs(_ date: Date) -> Bool { | |
guard let eod = date.endOfDay() else { return false } | |
if self > eod { | |
return false | |
} | |
guard let bod = date.beginningOfDay() else { return false } | |
if self < bod { | |
return false | |
} | |
return true | |
} | |
public var isToday: Bool { | |
return sameDayAs(Date()) | |
} | |
public var isInFuture: Bool { | |
return timeIntervalSinceNow > 0 | |
} | |
public var isInPast: Bool { | |
return timeIntervalSinceNow < 0 | |
} | |
// MARK: - Accessing date components quickly | |
public var nanosecond: Int? { return dateComponents([.nanosecond]).nanosecond } | |
public var second: Int? { return dateComponents([.second]).second } | |
public var minute: Int? { return dateComponents([.minute]).minute } | |
public var hour: Int? { return dateComponents([.hour]).hour } | |
public var day: Int? { return dateComponents([.year]).day } | |
public var month: Int? { return dateComponents([.month]).month } | |
public var year: Int? { return dateComponents([.year]).year } | |
// MARK: - Future and past constructor helpers | |
public func secondsInFuture(_ seconds: Int, calendar: Calendar = .current) -> Date? { | |
return calendar.date(byAdding: DateComponents(second: seconds), to: self) | |
} | |
public func secondsInPast(_ seconds: Int, calendar: Calendar = .current) -> Date? { | |
return secondsInFuture(-seconds, calendar: calendar) | |
} | |
public func minutesInFuture(_ minutes: Int, calendar: Calendar = .current) -> Date? { | |
return calendar.date(byAdding: DateComponents(minute: minutes), to: self) | |
} | |
public func minutesInPast(_ minutes: Int, calendar: Calendar = .current) -> Date? { | |
return minutesInFuture(-minutes, calendar: calendar) | |
} | |
public func hoursInFuture(_ hours: Int, calendar: Calendar = .current) -> Date? { | |
return calendar.date(byAdding: DateComponents(hour: hours), to: self) | |
} | |
public func hoursInPast(_ hours: Int, calendar: Calendar = .current) -> Date? { | |
return hoursInFuture(-hours, calendar: calendar) | |
} | |
public func daysInFuture(_ days: Int, calendar: Calendar = .current) -> Date? { | |
return calendar.date(byAdding: DateComponents(day: days), to: self) | |
} | |
public func daysInPast(_ days: Int, calendar: Calendar = .current) -> Date? { | |
return daysInFuture(-days, calendar: calendar) | |
} | |
public func monthsInFuture(_ months: Int, calendar: Calendar = .current) -> Date? { | |
return calendar.date(byAdding: DateComponents(month: months), to: self) | |
} | |
public func monthsInPast(_ months: Int, calendar: Calendar = .current) -> Date? { | |
return monthsInFuture(-months, calendar: calendar) | |
} | |
public func yearsInFuture(_ years: Int, calendar: Calendar = .current) -> Date? { | |
return calendar.date(byAdding: DateComponents(year: years), to: self) | |
} | |
public func yearsInPast(_ years: Int, calendar: Calendar = .current) -> Date? { | |
return yearsInFuture(-years, calendar: calendar) | |
} | |
} | |
// MARK: - Integer helpers | |
public extension Int { | |
/// Produce a date at x seconds ago | |
/// Returns: A Date set `self` seconds ago | |
public var secondsAgo: Date? { return Date().secondsInPast(self) } | |
/// Produce a date at x seconds into the future | |
/// Returns: A Date set `self` seconds into the future | |
public var secondsHence: Date? { return Date().secondsInFuture(self) } | |
/// Produce a date at x minutes ago | |
/// Returns: A Date set `self` minutes ago | |
public var minutesAgo: Date? { return Date().minutesInPast(self) } | |
/// Produce a date at x minutes into the future | |
/// Returns: A Date set `self` minutes into the future | |
public var minutesHence: Date? { return Date().minutesInFuture(self) } | |
/// Produce a date at x hours ago | |
/// Returns: A Date set `self` hours ago | |
public var hoursAgo: Date? { return Date().hoursInPast(self) } | |
/// Produce a date at x hours into the future | |
/// Returns: A Date set `self` hours into the future | |
public var hoursHence: Date? { return Date().hoursInFuture(self) } | |
/// Produce a date at x days ago | |
/// Returns: A Date set `self` days ago | |
public var daysAgo: Date? { return Date().daysInPast(self) } | |
/// Produce a date at x days into the future | |
/// Returns: A Date set `self` days into the future | |
public var daysHence: Date? { return Date().daysInFuture(self) } | |
/// Produce a date at x months ago | |
/// Returns: A Date set `self` months ago | |
public var monthsAgo: Date? { return Date().monthsInPast(self) } | |
/// Produce a date at x months into the future | |
/// Returns: A Date set `self` months into the future | |
public var monthsHence: Date? { return Date().monthsInFuture(self) } | |
/// Produce a date at x years ago | |
/// Returns: A Date set `self` years ago | |
public var yearsAgo: Date? { return Date().yearsInPast(self) } | |
/// Produce a date at x years into the future | |
/// Returns: A Date set `self` years into the future | |
public var yearsHence: Date? { return Date().yearsInFuture(self) } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment