//
|
// 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
|
}
|
|
}
|