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 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)!
comparing time without date swift3
Suggestion using DateComponents
Assuming this given array
let times = ["4:30 AM","1:00 PM","3:20 PM","6:40 PM","9:10 PM"]
Create a date formatter matching the format
let formatter = DateFormatter()
formatter.dateFormat = "h:mm a"Map the time strings to
Date
and immediately toDateComponents
considering onlyhour
andminute
let dateArray = times.map { Calendar.current.dateComponents([.hour, .minute], from:formatter.date(from:$0)!) }
Map this array to the next date from now matching the components respectively
let upcomingDates = dateArray.map { Calendar.current.nextDate(after: Date(), matching: $0, matchingPolicy: .nextTime)! }
Sort the array ascending, the first item is the date you are looking for
let nextDate = upcomingDates.sorted().first!
Use the formatter to convert the date back to a time string
print(formatter.string(from:nextDate))
Comparing Time in ios Swift
Compare the time by ignoring the date component -
func checkTime() -> Bool {
let dateFormatter: DateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "PKT")
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let startingSlot = "2000-01-01 08:00:00" //UTC
let endingSlot = "2000-01-01 23:00:00" //UTC
let date = Date()
let date1: Date = dateFormatter.date(from: startingSlot)!
let date2: Date = dateFormatter.date(from: endingSlot)!
let currentTime = 60*Calendar.current.component(.hour, from: date) + Calendar.current.component(.minute, from: date) + (Calendar.current.component(.second, from: date)/60) // in minutes
let time1 = 60*Calendar.current.component(.hour, from: date1) + Calendar.current.component(.minute, from: date1) + (Calendar.current.component(.second, from: date1)/60) // in minutes
let time2 = 60*Calendar.current.component(.hour, from: date2) + Calendar.current.component(.minute, from: date2) + (Calendar.current.component(.second, from: date1)/60) // in minutes
print(currentTime)
print(time1)
print(time2)
if(currentTime >= time1 && currentTime <= time2) {
return true
} else {
return false
}
}
Output-
1121
510
1410
true
Swift compare between time
You can use Calendar.current.date(bySetting...)
to set the hour/second/minute of an existing date. Then, compare those results.
func getDate() -> Bool {
let currentDate = Date()
let startDate = Calendar.current.date(bySettingHour: 7, minute: 0, second: 0, of: currentDate)
let endDate = Calendar.current.date(bySettingHour: 19, minute: 0, second: 0, of: currentDate)
guard let startDate = startDate, let endDate = endDate else {
fatalError("Date creation failed ⚠️")
}
print(startDate < currentDate && currentDate < endDate)
print(startDate)
print(endDate)
print(currentDate)
return startDate < currentDate && currentDate < endDate
}
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 { ... }
Compare DateComponents in swift
You can create dates from the DateComponents
and compare them. You can make DateComponents
conform to Comparable
:
extension DateComponents: Comparable {
public static func < (lhs: DateComponents, rhs: DateComponents) -> Bool {
let now = Date()
let calendar = Calendar.current
return calendar.date(byAdding: lhs, to: now)! < calendar.date(byAdding: rhs, to: now)!
}
}
Then you can do those comparisons:
DateComponents(year: 1) > DateComponents(month: 15) // => false
DateComponents(day: 10) > DateComponents(weekOfMonth: 1) // => true
You might also want to make it Equatable
:
extension DateComponents: Equatable {
public static func == (lhs: DateComponents, rhs: DateComponents) -> Bool {
let now = Date()
let calendar = Calendar.current
return calendar.date(byAdding: lhs, to: now)! == calendar.date(byAdding: rhs, to: now)!
}
}
Disclaimer: This revised answer is using the current date/time as the reference to ensure meaningful comparison of days and months (give that the number of days per month can change). Questions like “are there more than 30 days in a month” only makes sense if the caller supplies a reference date or we use “now” (which is what I’ve done above).
Note, by using “now” as the reference date, then comparisons like “which is greater, 24 hours or 1 day” will now incorporate daylight savings (e.g., depending upon whether your calendar will “spring forward”, “fall back”, or, the vast majority of the time, not change at all).
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
Comparing NSDates without time component
Use this Calendar
function to compare dates in iOS 8.0+
func compare(_ date1: Date, to date2: Date, toGranularity component: Calendar.Component) -> ComparisonResult
passing .day
as the unit
Use this function as follows:
let now = Date()
// "Sep 23, 2015, 10:26 AM"
let olderDate = Date(timeIntervalSinceNow: -10000)
// "Sep 23, 2015, 7:40 AM"
var order = Calendar.current.compare(now, to: olderDate, toGranularity: .hour)
switch order {
case .orderedDescending:
print("DESCENDING")
case .orderedAscending:
print("ASCENDING")
case .orderedSame:
print("SAME")
}
// Compare to hour: DESCENDING
var order = Calendar.current.compare(now, to: olderDate, toGranularity: .day)
switch order {
case .orderedDescending:
print("DESCENDING")
case .orderedAscending:
print("ASCENDING")
case .orderedSame:
print("SAME")
}
// Compare to day: SAME
Related Topics
Converting Url to String and Back Again
Continuously Train Coreml Model After Shipping
Default Optional Parameter in Swift Function
What Is the Swift Equivalent of -[Nsobject Description]
Animate Cell When Pressed Using Swift 3
How to Print Call Stack in Swift
Swift Enum Raw Value: Not Working with Cgfloat = -1.0
How to Link to a 3Rd Party Swift Framework
Nsmanagedobject Changes Do Not Trigger Objectwillchange
Read and Write Permission for User Selected Folder in MAC Os App
Slide Sidebar Menu iOS 8 Swift
Xcode 6, Swift - Read Standard Input (Console) to String
Alamofire Type 'Parameterencoding' Has No Member 'Url' Swift 3
How to Prevent Timer Slowing Down in Background
Nsdatecomponents Weekofyear Returns Wrong Date