Swift 3 - Comparing Date objects
I have tried this snippet (in Xcode 8 Beta 6), and it is working fine.
let date1 = Date()
let date2 = Date().addingTimeInterval(100)
if date1 == date2 { ... }
else if date1 > date2 { ... }
else if date1 < date2 { ... }
How can i compare two dates (NSDate) in Swift 3 and get the days between them?
Simply make extension of Date
like this and get difference in days.
extension Date {
func daysBetweenDate(toDate: Date) -> Int {
let components = Calendar.current.dateComponents([.day], from: self, to: toDate)
return components.day ?? 0
}
}
Now use this extension like this
let numOfDays = fromDate.daysBetweenDate(toDate: toDate)
You can use DateFormatter
to convert String to Date like this.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
let date = dateFormatter.date(from: "18-11-2016")
Comparing two dates in swift in order to check if a day has gone by
Your code cannot work.
The logic is supposed to be:
- Get the day from
UserDefaults
, - Compare it to the current day.
- If the values are not equal save the new day to
UserDefaults
class UserInfoViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let dateToday = Calendar.current.component(.day, from: Date())
let dateToCompare = UserDefaults.standard.integer(forKey: "userDefaultDate")
if dateToCompare != dateToCompare {
UserDefaults.standard.set(dateToday, forKey: "userDefaultDate")
resetLabel.isHidden = false
} else {
resetLabel.isHidden = true
}
}
}
Note:
Never use value(forKey:
with UserDefaults
.
There are many convenience methods and for objects use object(forKey:
Edit
It's more reliable to save the Date
object and compare using isDateInToday
of Calendar
class UserInfoViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let dateToday = Date()
let calendar = Calendar.current
let dateToCompare = UserDefaults.standard.object(forKey: "userDefaultDate") as? Date ?? Date.distantPast
if calendar.isDateInToday(dateToCompare) {
resetLabel.isHidden = true
} else {
UserDefaults.standard.set(dateToday, forKey: "userDefaultDate")
resetLabel.isHidden = false
}
}
}
Compare only time difference in Date objects
You can use Calendar
to extract the DateComponents
and then combine the day, month, and year from one with the hour, minute, and second of the other into another Date
object. Then you can compare the two Date
objects that share the same date using the well documented methods.
For example, given date1
and date2
, we can calculate date3
with date of date1
, but time of date2
. We can then compare date1
to this new date3
:
let calendar = Calendar.current
let components2 = calendar.dateComponents([.hour, .minute, .second], from: date2)
let date3 = calendar.date(bySettingHour: components2.hour!, minute: components2.minute!, second: components2.second!, of: date1)!
Then, to get the number of minutes between date1
and date3
:
let minutes = calendar.dateComponents([.minute], from: date1, to: date3).minute!
Or hours and minutes:
let difference = calendar.dateComponents([.hour, .minute], from: date1, to: date3)
let hours = difference.hour!
let minutes = difference.minute!
Or, if you want to show this to the user, you'd often use DateComponentsFormatter
to get a nice, localized string representation:
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [.hour, .minute] // or [.minute]
let string = formatter.string(from: date1, to: date3)!
Swift: Compare date by days
Details
- Xcode 11.5 (11E608c), Swift 5.1
Idea
base on usage dateComponents(_:from:to:) function
Solution
import Foundation
extension Date {
func fullDistance(from date: Date, resultIn component: Calendar.Component, calendar: Calendar = .current) -> Int? {
calendar.dateComponents([component], from: self, to: date).value(for: component)
}
func distance(from date: Date, only component: Calendar.Component, calendar: Calendar = .current) -> Int {
let days1 = calendar.component(component, from: self)
let days2 = calendar.component(component, from: date)
return days1 - days2
}
func hasSame(_ component: Calendar.Component, as date: Date) -> Bool {
distance(from: date, only: component) == 0
}
}
Full Sample
Do not forget to put here the Solution code (look above)
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy hh:mm:ss"
//dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let smallerDate = dateFormatter.date(from: "01-01-2012 00:05:01")!
let biggerDate = dateFormatter.date(from: "03-12-2019 09:30:01")!
print(smallerDate.fullDistance(from: biggerDate, resultIn: .day)) // Optional(2893)
print(biggerDate.fullDistance(from: smallerDate, resultIn: .day)) // Optional(-2893)
print(smallerDate.fullDistance(from: biggerDate, resultIn: .year)) // Optional(7)
print(biggerDate.fullDistance(from: smallerDate, resultIn: .year)) // Optional(7)
print(smallerDate.fullDistance(from: biggerDate, resultIn: .hour)) // Optional(69441)
print(biggerDate.fullDistance(from: smallerDate, resultIn: .hour)) // Optional(-69441)
print(smallerDate.distance(from: biggerDate, only: .day)) // -2
print(biggerDate.distance(from: smallerDate, only: .day)) // 2
print(smallerDate.distance(from: biggerDate, only: .year)) // -7
print(biggerDate.distance(from: smallerDate, only: .year)) // 7
print(smallerDate.distance(from: biggerDate, only: .hour)) // -9
print(biggerDate.distance(from: smallerDate, only: .hour)) // 9
print(smallerDate.hasSame(.day, as: biggerDate)) // false
print(biggerDate.hasSame(.second, as: smallerDate)) // true
How do you compare just the time of a Date in Swift?
This is the route I took in the end, which makes it easy to compare just the time of a Date in swift
New Object Time:
class Time: Comparable, Equatable {
init(_ date: Date) {
//get the current calender
let calendar = Calendar.current
//get just the minute and the hour of the day passed to it
let dateComponents = calendar.dateComponents([.hour, .minute], from: date)
//calculate the seconds since the beggining of the day for comparisions
let dateSeconds = dateComponents.hour! * 3600 + dateComponents.minute! * 60
//set the varibles
secondsSinceBeginningOfDay = dateSeconds
hour = dateComponents.hour!
minute = dateComponents.minute!
}
init(_ hour: Int, _ minute: Int) {
//calculate the seconds since the beggining of the day for comparisions
let dateSeconds = hour * 3600 + minute * 60
//set the varibles
secondsSinceBeginningOfDay = dateSeconds
self.hour = hour
self.minute = minute
}
var hour : Int
var minute: Int
var date: Date {
//get the current calender
let calendar = Calendar.current
//create a new date components.
var dateComponents = DateComponents()
dateComponents.hour = hour
dateComponents.minute = minute
return calendar.date(byAdding: dateComponents, to: Date())!
}
/// the number or seconds since the beggining of the day, this is used for comparisions
private let secondsSinceBeginningOfDay: Int
//comparisions so you can compare times
static func == (lhs: Time, rhs: Time) -> Bool {
return lhs.secondsSinceBeginningOfDay == rhs.secondsSinceBeginningOfDay
}
static func < (lhs: Time, rhs: Time) -> Bool {
return lhs.secondsSinceBeginningOfDay < rhs.secondsSinceBeginningOfDay
}
static func <= (lhs: Time, rhs: Time) -> Bool {
return lhs.secondsSinceBeginningOfDay <= rhs.secondsSinceBeginningOfDay
}
static func >= (lhs: Time, rhs: Time) -> Bool {
return lhs.secondsSinceBeginningOfDay >= rhs.secondsSinceBeginningOfDay
}
static func > (lhs: Time, rhs: Time) -> Bool {
return lhs.secondsSinceBeginningOfDay > rhs.secondsSinceBeginningOfDay
}
}
Date Extension for easy access:
//Adds ability to just get the time from a date:
extension Date {
var time: Time {
return Time(self)
}
}
Example:
let firstDate = Date()
let secondDate = firstDate
//Will return true
let timeEqual = firstDate.time == secondDate.time
Compare Date to String Date Value Swift
There is a better way to check if two dates are in the same day
let currentDate = Date()
let selectedDate = Date()
if Calendar.current.isDate(currentDate, inSameDayAs: selectedDate) {
print("yes")
} else {
print("no")
}
How to determine date falls in between two dates swift
If you have Date objects, they are Comparable and Equatable. You can write code like:
if breakDate >= startDate && breakDate <= endDate then {
// breakDate is between startDate and endDate
}
Edit:
As pointed out by LeoDabus in the comments, you could also use the pattern match operator (although I personally don't like it)
if startDate ... endDate ~= breakDate then {
// breakDate is between startDate and endDate
}
or contains:
if (startDate...endDate).contains(breakDate) then {
// breakDate is between startDate and endDate
}
If you have date strings, create a date formatter that converts your date strings to Date
objects, then use code like the above.
If the date strings are always in "Internet" date format (ISO 8601), and you are certain they will always be in the same time zone, you can also use string comparison and compare the date strings directly (using any of the above forms of comparison, except maybe contains?)
How to compare array of dates (Strings) with single date in swift 3
let clickedStr = TotalDaysServerArray[indexPath.row]
let str = clickedStr.components(separatedBy: " ").first
for(index , value) in datesFromDBArray.enumerated() {
if str == value.components(separatedBy: " ").first! {
print(ActionsDBArray[index])
}
}
Related Topics
Write Extend File Attributes Swift Example
Swift 4 "This Class Is Not Key Value Coding Compliant"
Capture Redirect Url in Wkwebview in iOS
Uitableview Checkmarks Disappear When Scrolling
Unwind Segue from Navigation Back Button in Swift
Offscreen Uitableviewcells (For Size Calculations) Not Respecting Size Class
How Could I Get an Array of Emojis Found in iOS8.3
Xcode 7.3.1 with iOS 10 Support
More Efficient Way to Retrieve Firebase Data
How to Show Alertview with Activity Indicator
How to Force Wkwebview to Ignore Hardware Silent Switch on iOS
How to Change App Icon Programmatically
Swift Image Retrieving from Parse Sdk - Getting Crashed
iOS Protocol/Delegate Confusion
Xcode 5.1: Missing Required Architecture Arm64