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
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
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))
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)!
Compare time duration values in Swift
You can use this String Extension to calculate total minutes from string
extension String {
func getTimeInSeconds()-> Int? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "mm:ss" //Your date format
dateFormatter.timeZone = TimeZone.current //Current time zone
var date = Date()
if let getDate = dateFormatter.date(from: self) {//according to date format your date string
date = getDate //Convert String to Date
} else {
dateFormatter.dateFormat = "hh:mm:ss"
if let getDate = dateFormatter.date(from: self) {//according to date format your date string
date = getDate //Convert String to Date
} else {
return nil
}
}
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute,.second], from: date)
let hour = components.hour ?? 0
let minute = components.minute ?? 0
let seconds = components.second ?? 0
return (hour * 360) + minute*60 + seconds
}
}
You can use this extension like this
let getSeconds = "01:20".getTimeInSeconds()
it will cover both formats mm:ss and hh:mm:ss and return seconds ... you can use these seconds to compare instead of string
Swift - Date String Compare
Here is a function that converts the given string to a date and compares it to the given dat (default today). By using startOfDay(for:)
time is ignored in the comparison
func before(_ string: String, date: Date = Date()) -> Bool? {
let locale = Locale(identifier: "en_US_POSIX")
let dateFormatter = DateFormatter()
dateFormatter.locale = locale
dateFormatter.dateFormat = "MMM dd, yyyy"
guard let inDate = dateFormatter.date(from: string) else {
return nil
}
var calendar = Calendar.current
calendar.locale = locale
return inDate < calendar.startOfDay(for: date)
}
Time comparisons in swift
You have compare function to compare 2 NSDate to know which one is more recent. It returns NSCompareResults
enum NSComparisonResult : Int {
case OrderedAscending
case OrderedSame
case OrderedDescending
}
Get distance (in seconds) from 2 NSDate, you have .timeIntervalSinceDate(). Then, you know how to convert to minutes, hours, ...
let date1 : NSDate = ...
let date2 : NSDate = ...
let compareResult = date1.compare(date2)
let interval = date1.timeIntervalSinceDate(date2)
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 times in an array?
Suppose we have this array:
let array = ["08:00", "23:00", "01:00", "04:00"]
A more convenient way of dealing with "bus times" would be to define a struct like so:
struct BusTime: Comparable, CustomStringConvertible {
let hour : Int
let minute : Int
static func < (lhs: BusTime, rhs: BusTime) -> Bool {
return (lhs.hour, lhs.minute) < (rhs.hour, rhs.minute)
}
var description: String {
get {
let formatter = NumberFormatter()
formatter.minimumIntegerDigits = 2
return formatter.string(for: hour)! + ":" + formatter.string(for: minute)!
}
}
}
N.B: In the rest of the answer I'll be force-unwrapping for brevity)
Let's create a sorted array of BusTime
s:
let busTimes: [BusTime] = array.map { str in
return BusTime(hour: Int(str.prefix(2))!, minute: Int(str.suffix(2))!)
}
var sortedBusTimes = busTimes.sorted()
Let's also define a variable nextBus
which represents the next bus time:
var nextBus: BusTime = sortedBusTimes[0]
Now, let's create a time that corresponds to say the current date:
let nowComps = Calendar.current.dateComponents([.hour, .minute], from: Date())
let now = BusTime(hour: nowComps.hour!, minute: nowComps.minute!)
With binary search, we'll be able to find the next bus time in O(log(n)):
var low = sortedBusTimes.startIndex
var high = sortedBusTimes.endIndex
while low < high {
let middle = low + (high - low)/2
let middleTime = sortedBusTimes[middle]
if middleTime == now {
low = middle
break
} else if middleTime < now {
low = middle + 1
} else if now < middleTime {
high = middle
}
}
if low != sortedBusTimes.endIndex, high != 0 {
nextBus = sortedBusTimes[low]
}
The definition middle
could be simpler this way:
let middle = low + (high - low)/2
But take this article into consideration.
Finally, let's check:
print(nextBus)
At the time of writing this answer, it is 17:52. So the result printed in the console is:
23:00
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")
}
Related Topics
Today Extension View Flashes When Redrawing
iOS Web App: Showing Content Only If the Application Is Standalone
Which Phassetcollection to Use for Saving an Image
How to Get MAC Address from Cbperipheral and Cbcenter
How to Show Specific Language Keyboard When User Input Values in Uitextfield in iPhone App
Ciimage Display Mtkview VS Glkview Performance
Add Custom Cordova Plugin to Ibm Worklight 6.1
Nsindexpath? Does Not Have a Member Name 'Row' Error in Swift
iOS - Custom Table Cell Not Full Width of Uitableview
Why Don't My Views Show Up in Storyboards and Are Greyed Out in the Left Pane
iOS - Spritekit - How to Calculate the Distance Between Two Nodes
In-App Purchase Sandbox Environment Loop
iOS App Getting Throttled from Local Searches
Didbegincontact Is Being Called Multiple Times for the Same Skphysicsbody