add all api to sort by month
This commit is contained in:
190
Sources/App/Libraries/SwiftDate/Date/Date+Compare.swift
Normal file
190
Sources/App/Libraries/SwiftDate/Date/Date+Compare.swift
Normal file
@@ -0,0 +1,190 @@
|
||||
//
|
||||
// SwiftDate
|
||||
// Parse, validate, manipulate, and display dates, time and timezones in Swift
|
||||
//
|
||||
// Created by Daniele Margutti
|
||||
// - Web: https://www.danielemargutti.com
|
||||
// - Twitter: https://twitter.com/danielemargutti
|
||||
// - Mail: hello@danielemargutti.com
|
||||
//
|
||||
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Date {
|
||||
|
||||
// MARK: - Comparing Close
|
||||
|
||||
/// Decides whether a Date is "close by" another one passed in parameter,
|
||||
/// where "Being close" is measured using a precision argument
|
||||
/// which is initialized a 300 seconds, or 5 minutes.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - refDate: reference date compare against to.
|
||||
/// - precision: The precision of the comparison (default is 5 minutes, or 300 seconds).
|
||||
/// - Returns: A boolean; true if close by, false otherwise.
|
||||
func compareCloseTo(_ refDate: Date, precision: TimeInterval = 300) -> Bool {
|
||||
return (abs(timeIntervalSince(refDate)) < precision)
|
||||
}
|
||||
|
||||
// MARK: - Extendend Compare
|
||||
|
||||
/// Compare the date with the rule specified in the `compareType` parameter.
|
||||
///
|
||||
/// - Parameter compareType: comparison type.
|
||||
/// - Returns: `true` if comparison succeded, `false` otherwise
|
||||
func compare(_ compareType: DateComparisonType) -> Bool {
|
||||
return inDefaultRegion().compare(compareType)
|
||||
}
|
||||
|
||||
/// Returns a ComparisonResult value that indicates the ordering of two given dates based on
|
||||
/// their components down to a given unit granularity.
|
||||
///
|
||||
/// - parameter date: date to compare.
|
||||
/// - parameter granularity: The smallest unit that must, along with all larger units be less for the given dates
|
||||
/// - returns: `ComparisonResult`
|
||||
func compare(toDate refDate: Date, granularity: Calendar.Component) -> ComparisonResult {
|
||||
return inDefaultRegion().compare(toDate: refDate.inDefaultRegion(), granularity: granularity)
|
||||
}
|
||||
|
||||
/// Compares whether the receiver is before/before equal `date` based on their components down to a given unit granularity.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - refDate: reference date
|
||||
/// - orEqual: `true` to also check for equality
|
||||
/// - granularity: smallest unit that must, along with all larger units, be less for the given dates
|
||||
/// - Returns: Boolean
|
||||
func isBeforeDate(_ refDate: Date, orEqual: Bool = false, granularity: Calendar.Component) -> Bool {
|
||||
return inDefaultRegion().isBeforeDate(refDate.inDefaultRegion(), orEqual: orEqual, granularity: granularity)
|
||||
}
|
||||
|
||||
/// Compares whether the receiver is after `date` based on their components down to a given unit granularity.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - refDate: reference date
|
||||
/// - orEqual: `true` to also check for equality
|
||||
/// - granularity: Smallest unit that must, along with all larger units, be greater for the given dates.
|
||||
/// - Returns: Boolean
|
||||
func isAfterDate(_ refDate: Date, orEqual: Bool = false, granularity: Calendar.Component) -> Bool {
|
||||
return inDefaultRegion().isAfterDate(refDate.inDefaultRegion(), orEqual: orEqual, granularity: granularity)
|
||||
}
|
||||
|
||||
/// Return true if receiver date is contained in the range specified by two dates.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - startDate: range upper bound date
|
||||
/// - endDate: range lower bound date
|
||||
/// - orEqual: `true` to also check for equality on date and date2
|
||||
/// - granularity: smallest unit that must, along with all larger units, be greater for the given dates.
|
||||
/// - Returns: Boolean
|
||||
func isInRange(date startDate: Date, and endDate: Date, orEqual: Bool = false, granularity: Calendar.Component = .nanosecond) -> Bool {
|
||||
return self.inDefaultRegion().isInRange(date: startDate.inDefaultRegion(), and: endDate.inDefaultRegion(), orEqual: orEqual, granularity: granularity)
|
||||
}
|
||||
|
||||
/// Compares equality of two given dates based on their components down to a given unit
|
||||
/// granularity.
|
||||
///
|
||||
/// - parameter date: date to compare
|
||||
/// - parameter granularity: The smallest unit that must, along with all larger units, be equal for the given
|
||||
/// dates to be considered the same.
|
||||
///
|
||||
/// - returns: `true` if the dates are the same down to the given granularity, otherwise `false`
|
||||
func isInside(date: Date, granularity: Calendar.Component) -> Bool {
|
||||
return (compare(toDate: date, granularity: granularity) == .orderedSame)
|
||||
}
|
||||
|
||||
// MARK: - Date Earlier/Later
|
||||
|
||||
/// Return the earlier of two dates, between self and a given date.
|
||||
///
|
||||
/// - Parameter date: The date to compare to self
|
||||
/// - Returns: The date that is earlier
|
||||
func earlierDate(_ date: Date) -> Date {
|
||||
return timeIntervalSince(date) <= 0 ? self : date
|
||||
}
|
||||
|
||||
/// Return the later of two dates, between self and a given date.
|
||||
///
|
||||
/// - Parameter date: The date to compare to self
|
||||
/// - Returns: The date that is later
|
||||
func laterDate(_ date: Date) -> Date {
|
||||
return timeIntervalSince(date) >= 0 ? self : date
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension Date {
|
||||
|
||||
/// Returns the difference in the calendar component given (like day, month or year)
|
||||
/// with respect to the other date as a positive integer
|
||||
public func difference(in component: Calendar.Component, from other: Date) -> Int? {
|
||||
let (max, min) = orderDate(with: other)
|
||||
let result = calendar.dateComponents([component], from: min, to: max)
|
||||
return getValue(of: component, from: result)
|
||||
}
|
||||
|
||||
/// Returns the differences in the calendar components given (like day, month and year)
|
||||
/// with respect to the other date as dictionary with the calendar component as the key
|
||||
/// and the diffrence as a positive integer as the value
|
||||
public func differences(in components: Set<Calendar.Component>, from other: Date) -> [Calendar.Component: Int] {
|
||||
let (max, min) = orderDate(with: other)
|
||||
let differenceInDates = calendar.dateComponents(components, from: min, to: max)
|
||||
var result = [Calendar.Component: Int]()
|
||||
for component in components {
|
||||
if let value = getValue(of: component, from: differenceInDates) {
|
||||
result[component] = value
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private func getValue(of component: Calendar.Component, from dateComponents: DateComponents) -> Int? {
|
||||
switch component {
|
||||
case .era:
|
||||
return dateComponents.era
|
||||
case .year:
|
||||
return dateComponents.year
|
||||
case .month:
|
||||
return dateComponents.month
|
||||
case .day:
|
||||
return dateComponents.day
|
||||
case .hour:
|
||||
return dateComponents.hour
|
||||
case .minute:
|
||||
return dateComponents.minute
|
||||
case .second:
|
||||
return dateComponents.second
|
||||
case .weekday:
|
||||
return dateComponents.weekday
|
||||
case .weekdayOrdinal:
|
||||
return dateComponents.weekdayOrdinal
|
||||
case .quarter:
|
||||
return dateComponents.quarter
|
||||
case .weekOfMonth:
|
||||
return dateComponents.weekOfMonth
|
||||
case .weekOfYear:
|
||||
return dateComponents.weekOfYear
|
||||
case .yearForWeekOfYear:
|
||||
return dateComponents.yearForWeekOfYear
|
||||
case .nanosecond:
|
||||
return dateComponents.nanosecond
|
||||
case .calendar, .timeZone:
|
||||
return nil
|
||||
@unknown default:
|
||||
assert(false, "unknown date component")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private func orderDate(with other: Date) -> (Date, Date) {
|
||||
let first = self.timeIntervalSince1970
|
||||
let second = other.timeIntervalSince1970
|
||||
|
||||
if first >= second {
|
||||
return (self, other)
|
||||
}
|
||||
|
||||
return (other, self)
|
||||
}
|
||||
}
|
||||
49
Sources/App/Libraries/SwiftDate/Date/Date+Components.swift
Normal file
49
Sources/App/Libraries/SwiftDate/Date/Date+Components.swift
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// SwiftDate
|
||||
// Parse, validate, manipulate, and display dates, time and timezones in Swift
|
||||
//
|
||||
// Created by Daniele Margutti
|
||||
// - Web: https://www.danielemargutti.com
|
||||
// - Twitter: https://twitter.com/danielemargutti
|
||||
// - Mail: hello@danielemargutti.com
|
||||
//
|
||||
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Date {
|
||||
|
||||
/// Indicates whether the month is a leap month.
|
||||
var isLeapMonth: Bool {
|
||||
return inDefaultRegion().isLeapMonth
|
||||
}
|
||||
|
||||
/// Indicates whether the year is a leap year.
|
||||
var isLeapYear: Bool {
|
||||
return inDefaultRegion().isLeapYear
|
||||
}
|
||||
|
||||
/// Julian day is the continuous count of days since the beginning of
|
||||
/// the Julian Period used primarily by astronomers.
|
||||
var julianDay: Double {
|
||||
return inDefaultRegion().julianDay
|
||||
}
|
||||
|
||||
/// The Modified Julian Date (MJD) was introduced by the Smithsonian Astrophysical Observatory
|
||||
/// in 1957 to record the orbit of Sputnik via an IBM 704 (36-bit machine)
|
||||
/// and using only 18 bits until August 7, 2576.
|
||||
var modifiedJulianDay: Double {
|
||||
return inDefaultRegion().modifiedJulianDay
|
||||
}
|
||||
|
||||
/// Return elapsed time expressed in given components since the current receiver and a reference date.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - refDate: reference date (`nil` to use current date in the same region of the receiver)
|
||||
/// - component: time unit to extract.
|
||||
/// - Returns: value
|
||||
func getInterval(toDate: Date?, component: Calendar.Component) -> Int64 {
|
||||
return inDefaultRegion().getInterval(toDate: toDate?.inDefaultRegion(), component: component)
|
||||
}
|
||||
}
|
||||
250
Sources/App/Libraries/SwiftDate/Date/Date+Create.swift
Normal file
250
Sources/App/Libraries/SwiftDate/Date/Date+Create.swift
Normal file
@@ -0,0 +1,250 @@
|
||||
//
|
||||
// SwiftDate
|
||||
// Parse, validate, manipulate, and display dates, time and timezones in Swift
|
||||
//
|
||||
// Created by Daniele Margutti
|
||||
// - Web: https://www.danielemargutti.com
|
||||
// - Twitter: https://twitter.com/danielemargutti
|
||||
// - Mail: hello@danielemargutti.com
|
||||
//
|
||||
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Date {
|
||||
|
||||
/// Return the oldest date in given list.
|
||||
///
|
||||
/// - Parameter list: list of dates
|
||||
/// - Returns: a tuple with the index of the oldest date and its instance.
|
||||
static func oldestIn(list: [Date]) -> Date? {
|
||||
guard list.count > 0 else { return nil }
|
||||
guard list.count > 1 else { return list.first! }
|
||||
return list.min(by: {
|
||||
return $0 < $1
|
||||
})
|
||||
}
|
||||
|
||||
/// Return the newest date in given list.
|
||||
///
|
||||
/// - Parameter list: list of dates
|
||||
/// - Returns: a tuple with the index of the oldest date and its instance.
|
||||
static func newestIn(list: [Date]) -> Date? {
|
||||
guard list.count > 0 else { return nil }
|
||||
guard list.count > 1 else { return list.first! }
|
||||
return list.max(by: {
|
||||
return $0 < $1
|
||||
})
|
||||
}
|
||||
|
||||
/// Enumerate dates between two intervals by adding specified time components defined by a function and return an array of dates.
|
||||
/// `startDate` interval will be the first item of the resulting array.
|
||||
/// The last item of the array is evaluated automatically and maybe not equal to `endDate`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - start: starting date
|
||||
/// - endDate: ending date
|
||||
/// - increment: increment function. It get the last generated date and require a valida `DateComponents` instance which define the increment
|
||||
/// - Returns: array of dates
|
||||
static func enumerateDates(from startDate: Date, to endDate: Date, increment: ((Date) -> (DateComponents))) -> [Date] {
|
||||
var dates: [Date] = []
|
||||
var currentDate = startDate
|
||||
|
||||
while currentDate <= endDate {
|
||||
dates.append(currentDate)
|
||||
currentDate = (currentDate + increment(currentDate))
|
||||
}
|
||||
return dates
|
||||
}
|
||||
|
||||
/// Enumerate dates between two intervals by adding specified time components and return an array of dates.
|
||||
/// `startDate` interval will be the first item of the resulting array.
|
||||
/// The last item of the array is evaluated automatically and maybe not equal to `endDate`.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - start: starting date
|
||||
/// - endDate: ending date
|
||||
/// - increment: components to add
|
||||
/// - Returns: array of dates
|
||||
static func enumerateDates(from startDate: Date, to endDate: Date, increment: DateComponents) -> [Date] {
|
||||
return Date.enumerateDates(from: startDate, to: endDate, increment: { _ in
|
||||
return increment
|
||||
})
|
||||
}
|
||||
|
||||
/// Round a given date time to the passed style (off|up|down).
|
||||
///
|
||||
/// - Parameter style: rounding mode.
|
||||
/// - Returns: rounded date
|
||||
func dateRoundedAt(at style: RoundDateMode) -> Date {
|
||||
return inDefaultRegion().dateRoundedAt(style).date
|
||||
}
|
||||
|
||||
/// Returns a new DateInRegion that is initialized at the start of a specified unit of time.
|
||||
///
|
||||
/// - Parameter unit: time unit value.
|
||||
/// - Returns: instance at the beginning of the time unit; `self` if fails.
|
||||
func dateAtStartOf(_ unit: Calendar.Component) -> Date {
|
||||
return inDefaultRegion().dateAtStartOf(unit).date
|
||||
}
|
||||
|
||||
/// Return a new DateInRegion that is initialized at the start of the specified components
|
||||
/// executed in order.
|
||||
///
|
||||
/// - Parameter units: sequence of transformations as time unit components
|
||||
/// - Returns: new date at the beginning of the passed components, intermediate results if fails.
|
||||
func dateAtStartOf(_ units: [Calendar.Component]) -> Date {
|
||||
return units.reduce(self) { (currentDate, currentUnit) -> Date in
|
||||
return currentDate.dateAtStartOf(currentUnit)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new Moment that is initialized at the end of a specified unit of time.
|
||||
///
|
||||
/// - parameter unit: A TimeUnit value.
|
||||
///
|
||||
/// - returns: A new Moment instance.
|
||||
func dateAtEndOf(_ unit: Calendar.Component) -> Date {
|
||||
return inDefaultRegion().dateAtEndOf(unit).date
|
||||
}
|
||||
|
||||
/// Return a new DateInRegion that is initialized at the end of the specified components
|
||||
/// executed in order.
|
||||
///
|
||||
/// - Parameter units: sequence of transformations as time unit components
|
||||
/// - Returns: new date at the end of the passed components, intermediate results if fails.
|
||||
func dateAtEndOf(_ units: [Calendar.Component]) -> Date {
|
||||
return units.reduce(self) { (currentDate, currentUnit) -> Date in
|
||||
return currentDate.dateAtEndOf(currentUnit)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new date by altering specified components of the receiver.
|
||||
///
|
||||
/// - Parameter components: components to alter with their new values.
|
||||
/// - Returns: new altered `DateInRegion` instance
|
||||
func dateBySet(_ components: [Calendar.Component: Int]) -> Date? {
|
||||
return DateInRegion(self, region: SwiftDate.defaultRegion).dateBySet(components)?.date
|
||||
}
|
||||
|
||||
/// Create a new date by altering specified time components.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - hour: hour to set (`nil` to leave it unaltered)
|
||||
/// - min: min to set (`nil` to leave it unaltered)
|
||||
/// - secs: sec to set (`nil` to leave it unaltered)
|
||||
/// - ms: milliseconds to set (`nil` to leave it unaltered)
|
||||
/// - options: options for calculation
|
||||
/// - Returns: new altered `DateInRegion` instance
|
||||
func dateBySet(hour: Int?, min: Int?, secs: Int?, ms: Int? = nil, options: TimeCalculationOptions = TimeCalculationOptions()) -> Date? {
|
||||
let srcDate = DateInRegion(self, region: SwiftDate.defaultRegion)
|
||||
return srcDate.dateBySet(hour: hour, min: min, secs: secs, ms: ms, options: options)?.date
|
||||
}
|
||||
|
||||
/// Creates a new instance by truncating the components
|
||||
///
|
||||
/// - Parameter components: components to truncate.
|
||||
/// - Returns: new date with truncated components.
|
||||
func dateTruncated(_ components: [Calendar.Component]) -> Date? {
|
||||
return DateInRegion(self, region: SwiftDate.defaultRegion).dateTruncated(at: components)?.date
|
||||
}
|
||||
|
||||
/// Creates a new instance by truncating the components starting from given components down the granurality.
|
||||
///
|
||||
/// - Parameter component: The component to be truncated from.
|
||||
/// - Returns: new date with truncated components.
|
||||
func dateTruncated(from component: Calendar.Component) -> Date? {
|
||||
return DateInRegion(self, region: SwiftDate.defaultRegion).dateTruncated(from: component)?.date
|
||||
}
|
||||
|
||||
/// Offset a date by n calendar components.
|
||||
/// Note: This operation can be functionally chained.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - count: value of the offset.
|
||||
/// - component: component to offset.
|
||||
/// - Returns: new altered date.
|
||||
func dateByAdding(_ count: Int, _ component: Calendar.Component) -> DateInRegion {
|
||||
return DateInRegion(self, region: SwiftDate.defaultRegion).dateByAdding(count, component)
|
||||
}
|
||||
|
||||
/// Return related date starting from the receiver attributes.
|
||||
///
|
||||
/// - Parameter type: related date to obtain.
|
||||
/// - Returns: instance of the related date.
|
||||
func dateAt(_ type: DateRelatedType) -> Date {
|
||||
return inDefaultRegion().dateAt(type).date
|
||||
}
|
||||
|
||||
/// Create a new date at now and extract the related date using passed rule type.
|
||||
///
|
||||
/// - Parameter type: related date to obtain.
|
||||
/// - Returns: instance of the related date.
|
||||
static func nowAt(_ type: DateRelatedType) -> Date {
|
||||
return Date().dateAt(type)
|
||||
}
|
||||
|
||||
/// Return the dates for a specific weekday inside given month of specified year.
|
||||
/// Ie. get me all the saturdays of Feb 2018.
|
||||
/// NOTE: Values are returned in order.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - weekday: weekday target.
|
||||
/// - month: month target.
|
||||
/// - year: year target.
|
||||
/// - region: region target, omit to use `SwiftDate.defaultRegion`
|
||||
/// - Returns: Ordered list of the dates for given weekday into given month.
|
||||
static func datesForWeekday(_ weekday: WeekDay, inMonth month: Int, ofYear year: Int,
|
||||
region: Region = SwiftDate.defaultRegion) -> [Date] {
|
||||
let fromDate = DateInRegion(Date(year: year, month: month, day: 1, hour: 0, minute: 0), region: region)
|
||||
let toDate = fromDate.dateAt(.endOfMonth)
|
||||
return DateInRegion.datesForWeekday(weekday, from: fromDate, to: toDate, region: region).map { $0.date }
|
||||
}
|
||||
|
||||
/// Return the dates for a specific weekday inside a specified date range.
|
||||
/// NOTE: Values are returned in order.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - weekday: weekday target.
|
||||
/// - startDate: from date of the range.
|
||||
/// - endDate: to date of the range.
|
||||
/// - region: region target, omit to use `SwiftDate.defaultRegion`
|
||||
/// - Returns: Ordered list of the dates for given weekday in passed range.
|
||||
static func datesForWeekday(_ weekday: WeekDay, from startDate: Date, to endDate: Date,
|
||||
region: Region = SwiftDate.defaultRegion) -> [Date] {
|
||||
let fromDate = DateInRegion(startDate, region: region)
|
||||
let toDate = DateInRegion(endDate, region: region)
|
||||
return DateInRegion.datesForWeekday(weekday, from: fromDate, to: toDate, region: region).map { $0.date }
|
||||
}
|
||||
|
||||
/// Returns the date at the given week number and week day preserving smaller components (hour, minute, seconds)
|
||||
///
|
||||
/// For example: to get the third friday of next month
|
||||
/// let today = DateInRegion()
|
||||
/// let result = today.dateAt(weekdayOrdinal: 3, weekday: .friday, monthNumber: today.month + 1)
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - weekdayOrdinal: the week number (by set position in a recurrence rule)
|
||||
/// - weekday: WeekDay
|
||||
/// - monthNumber: a number from 1 to 12 representing the month, optional parameter
|
||||
/// - yearNumber: a number representing the year, optional parameter
|
||||
/// - Returns: new date created with the given parameters
|
||||
func dateAt(weekdayOrdinal: Int, weekday: WeekDay, monthNumber: Int? = nil,
|
||||
yearNumber: Int? = nil) -> Date {
|
||||
let date = DateInRegion(self, region: region)
|
||||
return date.dateAt(weekdayOrdinal: weekdayOrdinal, weekday: weekday, monthNumber: monthNumber, yearNumber: yearNumber).date
|
||||
}
|
||||
|
||||
/// Returns the next weekday preserving smaller components (hour, minute, seconds)
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - weekday: weekday to get.
|
||||
/// - region: region target, omit to use `SwiftDate.defaultRegion`
|
||||
/// - Returns: `Date`
|
||||
func nextWeekday(_ weekday: WeekDay, region: Region = SwiftDate.defaultRegion) -> Date {
|
||||
let date = DateInRegion(self, region: region)
|
||||
return date.nextWeekday(weekday).date
|
||||
}
|
||||
|
||||
}
|
||||
40
Sources/App/Libraries/SwiftDate/Date/Date+Math.swift
Normal file
40
Sources/App/Libraries/SwiftDate/Date/Date+Math.swift
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// SwiftDate
|
||||
// Parse, validate, manipulate, and display dates, time and timezones in Swift
|
||||
//
|
||||
// Created by Daniele Margutti
|
||||
// - Web: https://www.danielemargutti.com
|
||||
// - Twitter: https://twitter.com/danielemargutti
|
||||
// - Mail: hello@danielemargutti.com
|
||||
//
|
||||
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Subtracts two dates and returns the relative components from `lhs` to `rhs`.
|
||||
/// Follows this mathematical pattern:
|
||||
/// let difference = lhs - rhs
|
||||
/// rhs + difference = lhs
|
||||
public func - (lhs: Date, rhs: Date) -> DateComponents {
|
||||
return SwiftDate.defaultRegion.calendar.dateComponents(DateComponents.allComponentsSet, from: rhs, to: lhs)
|
||||
}
|
||||
|
||||
/// Adds date components to a date and returns a new date.
|
||||
public func + (lhs: Date, rhs: DateComponents) -> Date {
|
||||
return rhs.from(lhs)!
|
||||
}
|
||||
|
||||
/// Adds date components to a date and returns a new date.
|
||||
public func + (lhs: DateComponents, rhs: Date) -> Date {
|
||||
return (rhs + lhs)
|
||||
}
|
||||
|
||||
/// Subtracts date components from a date and returns a new date.
|
||||
public func - (lhs: Date, rhs: DateComponents) -> Date {
|
||||
return (lhs + (-rhs))
|
||||
}
|
||||
|
||||
public func + (lhs: Date, rhs: TimeInterval) -> Date {
|
||||
return lhs.addingTimeInterval(rhs)
|
||||
}
|
||||
162
Sources/App/Libraries/SwiftDate/Date/Date.swift
Normal file
162
Sources/App/Libraries/SwiftDate/Date/Date.swift
Normal file
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// SwiftDate
|
||||
// Parse, validate, manipulate, and display dates, time and timezones in Swift
|
||||
//
|
||||
// Created by Daniele Margutti
|
||||
// - Web: https://www.danielemargutti.com
|
||||
// - Twitter: https://twitter.com/danielemargutti
|
||||
// - Mail: hello@danielemargutti.com
|
||||
//
|
||||
// Copyright © 2019 Daniele Margutti. Licensed under MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if os(Linux)
|
||||
|
||||
#else
|
||||
internal enum AssociatedKeys: String {
|
||||
case customDateFormatter = "SwiftDate.CustomDateFormatter"
|
||||
}
|
||||
#endif
|
||||
|
||||
extension Date: DateRepresentable {
|
||||
|
||||
/// Just return itself to be compliant with `DateRepresentable` protocol.
|
||||
public var date: Date { return self }
|
||||
|
||||
/// For absolute Date object the default region is obtained from the global `defaultRegion` variable.
|
||||
public var region: Region {
|
||||
return SwiftDate.defaultRegion
|
||||
}
|
||||
|
||||
#if os(Linux)
|
||||
public var customFormatter: DateFormatter? {
|
||||
get {
|
||||
debugPrint("Not supported on Linux")
|
||||
return nil
|
||||
}
|
||||
set { debugPrint("Not supported on Linux") }
|
||||
}
|
||||
#else
|
||||
/// Assign a custom formatter if you need a special behaviour during formatting of the object.
|
||||
/// Usually you will not need to do it, SwiftDate uses the local thread date formatter in order to
|
||||
/// optimize the formatting process. By default is `nil`.
|
||||
public var customFormatter: DateFormatter? {
|
||||
get {
|
||||
let fomatter: DateFormatter? = getAssociatedValue(key: AssociatedKeys.customDateFormatter.rawValue, object: self as AnyObject)
|
||||
return fomatter
|
||||
}
|
||||
set {
|
||||
set(associatedValue: newValue, key: AssociatedKeys.customDateFormatter.rawValue, object: self as AnyObject)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Extract the date components.
|
||||
public var dateComponents: DateComponents {
|
||||
return region.calendar.dateComponents(DateComponents.allComponentsSet, from: self)
|
||||
}
|
||||
|
||||
/// Initialize a new date object from string expressed in given region.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - string: date expressed as string.
|
||||
/// - format: format of the date (`nil` uses provided list of auto formats patterns.
|
||||
/// Pass it if you can in order to optimize the parse task).
|
||||
/// - region: region in which the date is expressed. `nil` uses the `SwiftDate.defaultRegion`.
|
||||
public init?(_ string: String, format: String? = nil, region: Region = SwiftDate.defaultRegion) {
|
||||
guard let dateInRegion = DateInRegion(string, format: format, region: region) else { return nil }
|
||||
self = dateInRegion.date
|
||||
}
|
||||
|
||||
/// Initialize a new date from the number of seconds passed since Unix Epoch.
|
||||
///
|
||||
/// - Parameter interval: seconds
|
||||
|
||||
/// Initialize a new date from the number of seconds passed since Unix Epoch.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - interval: seconds from Unix epoch time.
|
||||
/// - region: region in which the date, `nil` uses the default region at UTC timezone
|
||||
public init(seconds interval: TimeInterval, region: Region = Region.UTC) {
|
||||
self = DateInRegion(seconds: interval, region: region).date
|
||||
}
|
||||
|
||||
/// Initialize a new date corresponding to the number of milliseconds since the Unix Epoch.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - interval: seconds since the Unix Epoch timestamp.
|
||||
/// - region: region in which the date must be expressed, `nil` uses the default region at UTC timezone
|
||||
public init(milliseconds interval: Int, region: Region = Region.UTC) {
|
||||
self = DateInRegion(milliseconds: interval, region: region).date
|
||||
}
|
||||
|
||||
/// Initialize a new date with the opportunity to configure single date components via builder pattern.
|
||||
/// Date is therfore expressed in passed region (`DateComponents`'s `timezone`,`calendar` and `locale` are ignored
|
||||
/// and overwritten by the region if not `nil`).
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - configuration: configuration callback
|
||||
/// - region: region in which the date is expressed. Ignore to use `SwiftDate.defaultRegion`, `nil` to use `DateComponents` data.
|
||||
public init?(components configuration: ((inout DateComponents) -> Void), region: Region? = SwiftDate.defaultRegion) {
|
||||
guard let date = DateInRegion(components: configuration, region: region)?.date else { return nil }
|
||||
self = date
|
||||
}
|
||||
|
||||
/// Initialize a new date with given components.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - components: components of the date.
|
||||
/// - region: region in which the date is expressed.
|
||||
/// Ignore to use `SwiftDate.defaultRegion`, `nil` to use `DateComponents` data.
|
||||
public init?(components: DateComponents, region: Region?) {
|
||||
guard let date = DateInRegion(components: components, region: region)?.date else { return nil }
|
||||
self = date
|
||||
}
|
||||
|
||||
/// Initialize a new date with given components.
|
||||
public init(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0, region: Region = SwiftDate.defaultRegion) {
|
||||
var components = DateComponents()
|
||||
components.year = year
|
||||
components.month = month
|
||||
components.day = day
|
||||
components.hour = hour
|
||||
components.minute = minute
|
||||
components.second = second
|
||||
components.nanosecond = nanosecond
|
||||
components.timeZone = region.timeZone
|
||||
components.calendar = region.calendar
|
||||
self = region.calendar.date(from: components)!
|
||||
}
|
||||
|
||||
/// Express given absolute date in the context of the default region.
|
||||
///
|
||||
/// - Returns: `DateInRegion`
|
||||
public func inDefaultRegion() -> DateInRegion {
|
||||
return DateInRegion(self, region: SwiftDate.defaultRegion)
|
||||
}
|
||||
|
||||
/// Express given absolute date in the context of passed region.
|
||||
///
|
||||
/// - Parameter region: destination region.
|
||||
/// - Returns: `DateInRegion`
|
||||
public func `in`(region: Region) -> DateInRegion {
|
||||
return DateInRegion(self, region: region)
|
||||
}
|
||||
|
||||
/// Return a date in the distant past.
|
||||
///
|
||||
/// - Returns: Date instance.
|
||||
public static func past() -> Date {
|
||||
return Date.distantPast
|
||||
}
|
||||
|
||||
/// Return a date in the distant future.
|
||||
///
|
||||
/// - Returns: Date instance.
|
||||
public static func future() -> Date {
|
||||
return Date.distantFuture
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user