308 lines
11 KiB
Swift
308 lines
11 KiB
Swift
//
|
|
// DateExtensions.swift
|
|
// EZSwiftExtensions
|
|
//
|
|
// Created by Goktug Yilmaz on 15/07/15.
|
|
// Copyright (c) 2015 Goktug Yilmaz. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// EZSE: This Date Formatter Manager help to cache already created formatter in a synchronized Dictionary to use them in future, helps in performace improvement.
|
|
|
|
class DateFormattersManager {
|
|
public static var dateFormatters: SynchronizedDictionary = SynchronizedDictionary<String, DateFormatter>()
|
|
}
|
|
|
|
extension Date {
|
|
|
|
public static let minutesInAWeek = 24 * 60 * 7
|
|
|
|
/// EZSE: Initializes Date from string and format
|
|
public init?(fromString string: String,
|
|
format: String,
|
|
timezone: TimeZone = TimeZone.autoupdatingCurrent,
|
|
locale: Locale = Locale.current) {
|
|
if let dateFormatter = DateFormattersManager.dateFormatters.getValue(for: format) {
|
|
if let date = dateFormatter.date(from: string) {
|
|
self = date
|
|
} else {
|
|
return nil
|
|
}
|
|
} else {
|
|
let formatter = DateFormatter()
|
|
formatter.timeZone = timezone
|
|
formatter.locale = locale
|
|
formatter.dateFormat = format
|
|
DateFormattersManager.dateFormatters.setValue(for: format, value: formatter)
|
|
if let date = formatter.date(from: string) {
|
|
self = date
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
/// EZSE: Initializes Date from string returned from an http response, according to several RFCs / ISO
|
|
public init?(httpDateString: String) {
|
|
if let rfc1123 = Date(fromString: httpDateString, format: "EEE',' dd' 'MMM' 'yyyy HH':'mm':'ss zzz") {
|
|
self = rfc1123
|
|
return
|
|
}
|
|
if let rfc850 = Date(fromString: httpDateString, format: "EEEE',' dd'-'MMM'-'yy HH':'mm':'ss z") {
|
|
self = rfc850
|
|
return
|
|
}
|
|
if let asctime = Date(fromString: httpDateString, format: "EEE MMM d HH':'mm':'ss yyyy") {
|
|
self = asctime
|
|
return
|
|
}
|
|
if let iso8601DateOnly = Date(fromString: httpDateString, format: "yyyy-MM-dd") {
|
|
self = iso8601DateOnly
|
|
return
|
|
}
|
|
if let iso8601DateHrMinOnly = Date(fromString: httpDateString, format: "yyyy-MM-dd'T'HH:mmxxxxx") {
|
|
self = iso8601DateHrMinOnly
|
|
return
|
|
}
|
|
if let iso8601DateHrMinSecOnly = Date(fromString: httpDateString, format: "yyyy-MM-dd'T'HH:mm:ssxxxxx") {
|
|
self = iso8601DateHrMinSecOnly
|
|
return
|
|
}
|
|
if let iso8601DateHrMinSecMs = Date(fromString: httpDateString, format: "yyyy-MM-dd'T'HH:mm:ss.SSSxxxxx") {
|
|
self = iso8601DateHrMinSecMs
|
|
return
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// EZSE: Converts Date to String
|
|
public func toString(dateStyle: DateFormatter.Style = .medium, timeStyle: DateFormatter.Style = .medium) -> String {
|
|
let formatter = DateFormatter()
|
|
formatter.dateStyle = dateStyle
|
|
formatter.timeStyle = timeStyle
|
|
return formatter.string(from: self)
|
|
}
|
|
|
|
/// EZSE: Converts Date to String, with format
|
|
public func toString(format: String) -> String {
|
|
|
|
let dateFormatter = getDateFormatter(for: format)
|
|
return dateFormatter.string(from: self)
|
|
}
|
|
|
|
/// EZSE: Use to get dateFormatter from synchronized Dict via dateFormatterManager
|
|
private func getDateFormatter(for format: String) -> DateFormatter {
|
|
|
|
var dateFormatter: DateFormatter?
|
|
if let _dateFormatter = DateFormattersManager.dateFormatters.getValue(for: format) {
|
|
dateFormatter = _dateFormatter
|
|
} else {
|
|
dateFormatter = createDateFormatter(for: format)
|
|
}
|
|
|
|
return dateFormatter!
|
|
}
|
|
|
|
///EZSE: CreateDateFormatter if formatter doesn't exist in Dict.
|
|
private func createDateFormatter(for format: String) -> DateFormatter {
|
|
let formatter = DateFormatter()
|
|
formatter.dateFormat = format
|
|
DateFormattersManager.dateFormatters.setValue(for: format, value: formatter)
|
|
return formatter
|
|
}
|
|
|
|
/// EZSE: Calculates how many days passed from now to date
|
|
public func daysInBetweenDate(_ date: Date) -> Double {
|
|
var diff = self.timeIntervalSince1970 - date.timeIntervalSince1970
|
|
diff = fabs(diff/86400)
|
|
return diff
|
|
}
|
|
|
|
/// EZSE: Calculates how many hours passed from now to date
|
|
public func hoursInBetweenDate(_ date: Date) -> Double {
|
|
var diff = self.timeIntervalSince1970 - date.timeIntervalSince1970
|
|
diff = fabs(diff/3600)
|
|
return diff
|
|
}
|
|
|
|
/// EZSE: Calculates how many minutes passed from now to date
|
|
public func minutesInBetweenDate(_ date: Date) -> Double {
|
|
var diff = self.timeIntervalSince1970 - date.timeIntervalSince1970
|
|
diff = fabs(diff/60)
|
|
return diff
|
|
}
|
|
|
|
/// EZSE: Calculates how many seconds passed from now to date
|
|
public func secondsInBetweenDate(_ date: Date) -> Double {
|
|
var diff = self.timeIntervalSince1970 - date.timeIntervalSince1970
|
|
diff = fabs(diff)
|
|
return diff
|
|
}
|
|
|
|
/// EZSE: Easy creation of time passed String. Can be Years, Months, days, hours, minutes or seconds
|
|
public func timePassed() -> String {
|
|
let date = Date()
|
|
let calendar = Calendar.autoupdatingCurrent
|
|
let components = (calendar as NSCalendar).components([.year, .month, .day, .hour, .minute, .second], from: self, to: date, options: [])
|
|
var str: String
|
|
|
|
if components.year! >= 1 {
|
|
components.year == 1 ? (str = "year") : (str = "years")
|
|
return "\(components.year!) \(str) ago"
|
|
} else if components.month! >= 1 {
|
|
components.month == 1 ? (str = "month") : (str = "months")
|
|
return "\(components.month!) \(str) ago"
|
|
} else if components.day! >= 1 {
|
|
components.day == 1 ? (str = "day") : (str = "days")
|
|
return "\(components.day!) \(str) ago"
|
|
} else if components.hour! >= 1 {
|
|
components.hour == 1 ? (str = "hour") : (str = "hours")
|
|
return "\(components.hour!) \(str) ago"
|
|
} else if components.minute! >= 1 {
|
|
components.minute == 1 ? (str = "minute") : (str = "minutes")
|
|
return "\(components.minute!) \(str) ago"
|
|
} else if components.second! >= 1 {
|
|
components.second == 1 ? (str = "second") : (str = "seconds")
|
|
return "\(components.second!) \(str) ago"
|
|
} else {
|
|
return "Just now"
|
|
}
|
|
}
|
|
|
|
/// EZSE: Easy creation of time passed String. Can be Years, Months, days, hours, minutes or seconds. Useful for localization
|
|
public func timePassed() -> TimePassed {
|
|
|
|
let date = Date()
|
|
let calendar = Calendar.autoupdatingCurrent
|
|
let components = (calendar as NSCalendar).components([.year, .month, .day, .hour, .minute, .second], from: self, to: date, options: [])
|
|
|
|
if components.year! >= 1 {
|
|
return TimePassed.year(components.year!)
|
|
} else if components.month! >= 1 {
|
|
return TimePassed.month(components.month!)
|
|
} else if components.day! >= 1 {
|
|
return TimePassed.day(components.day!)
|
|
} else if components.hour! >= 1 {
|
|
return TimePassed.hour(components.hour!)
|
|
} else if components.minute! >= 1 {
|
|
return TimePassed.minute(components.minute!)
|
|
} else if components.second! >= 1 {
|
|
return TimePassed.second(components.second!)
|
|
} else {
|
|
return TimePassed.now
|
|
}
|
|
}
|
|
|
|
/// EZSE: Check if date is in future.
|
|
public var isFuture: Bool {
|
|
return self > Date()
|
|
}
|
|
|
|
/// EZSE: Check if date is in past.
|
|
public var isPast: Bool {
|
|
return self < Date()
|
|
}
|
|
|
|
// EZSE: Check date if it is today
|
|
public var isToday: Bool {
|
|
let format = "yyyy-MM-dd"
|
|
let dateFormatter = getDateFormatter(for: format)
|
|
return dateFormatter.string(from: self) == dateFormatter.string(from: Date())
|
|
}
|
|
|
|
/// EZSE: Check date if it is yesterday
|
|
public var isYesterday: Bool {
|
|
let format = "yyyy-MM-dd"
|
|
let yesterDay = Calendar.current.date(byAdding: .day, value: -1, to: Date())
|
|
let dateFormatter = getDateFormatter(for: format)
|
|
return dateFormatter.string(from: self) == dateFormatter.string(from: yesterDay!)
|
|
}
|
|
|
|
/// EZSE: Check date if it is tomorrow
|
|
public var isTomorrow: Bool {
|
|
let format = "yyyy-MM-dd"
|
|
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: Date())
|
|
let dateFormatter = getDateFormatter(for: format)
|
|
|
|
return dateFormatter.string(from: self) == dateFormatter.string(from: tomorrow!)
|
|
}
|
|
|
|
/// EZSE: Check date if it is within this month.
|
|
public var isThisMonth: Bool {
|
|
let today = Date()
|
|
return self.month == today.month && self.year == today.year
|
|
}
|
|
|
|
/// EZSE: Check date if it is within this week.
|
|
public var isThisWeek: Bool {
|
|
return self.minutesInBetweenDate(Date()) <= Double(Date.minutesInAWeek)
|
|
}
|
|
|
|
/// EZSE: Get the era from the date
|
|
public var era: Int {
|
|
return Calendar.current.component(Calendar.Component.era, from: self)
|
|
}
|
|
|
|
/// EZSE : Get the year from the date
|
|
public var year: Int {
|
|
return Calendar.current.component(Calendar.Component.year, from: self)
|
|
}
|
|
|
|
/// EZSE : Get the month from the date
|
|
public var month: Int {
|
|
return Calendar.current.component(Calendar.Component.month, from: self)
|
|
}
|
|
|
|
/// EZSE : Get the weekday from the date
|
|
public var weekday: String {
|
|
let format = "EEEE"
|
|
let dateFormatter = getDateFormatter(for: format)
|
|
return dateFormatter.string(from: self)
|
|
}
|
|
|
|
// EZSE : Get the month from the date
|
|
public var monthAsString: String {
|
|
let format = "MMMM"
|
|
let dateFormatter = getDateFormatter(for: format)
|
|
return dateFormatter.string(from: self)
|
|
}
|
|
|
|
// EZSE : Get the day from the date
|
|
public var day: Int {
|
|
return Calendar.current.component(.day, from: self)
|
|
}
|
|
|
|
/// EZSE: Get the hours from date
|
|
public var hour: Int {
|
|
return Calendar.current.component(.hour, from: self)
|
|
}
|
|
|
|
/// EZSE: Get the minute from date
|
|
public var minute: Int {
|
|
return Calendar.current.component(.minute, from: self)
|
|
}
|
|
|
|
/// EZSE: Get the second from the date
|
|
public var second: Int {
|
|
return Calendar.current.component(.second, from: self)
|
|
}
|
|
|
|
/// EZSE : Gets the nano second from the date
|
|
public var nanosecond: Int {
|
|
return Calendar.current.component(.nanosecond, from: self)
|
|
}
|
|
|
|
#if os(iOS) || os(tvOS)
|
|
|
|
/// EZSE : Gets the international standard(ISO8601) representation of date
|
|
@available(iOS 10.0, *)
|
|
@available(tvOS 10.0, *)
|
|
public var iso8601: String {
|
|
let formatter = ISO8601DateFormatter()
|
|
return formatter.string(from: self)
|
|
}
|
|
|
|
#endif
|
|
}
|