Skip to content

Instantly share code, notes, and snippets.

@acrookston
Created February 7, 2018 18:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save acrookston/fdb7da75bf6a1b0935eae89ecef10c28 to your computer and use it in GitHub Desktop.
Save acrookston/fdb7da75bf6a1b0935eae89ecef10c28 to your computer and use it in GitHub Desktop.
Swift Date helpers
//
// 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