I have two Date Objects:
2017-01-13 11:40:17 +0000
2016-03-15 10:22:14 +0000
I need to compare
This code works, check it easily in playground
let s1 = "22:31"
let s2 = "14:31"
let f = DateFormatter()
f.dateFormat = "HH:mm"
f.date(from: s1)! //"Jan 1, 2000 at 10:31 PM"
f.date(from: s2)! //"Jan 1, 2000 at 2:31 PM"
f.date(from: s1)! > f.date(from: s2)! // true
My solution for comparing two times of day while ignoring the date:
let date1 = some time as a date
let date2 = some other time as a date
let time1 = 60*Calendar.current.component(.hour, from: date1!) + Calendar.current.component(.minute, from: date1!)
let time2 = 60*Calendar.current.component(.hour, from: date2!) + Calendar.current.component(.minute, from: date2!)
Now you can compare the integers time1 and time2 without regard to the day. You could add the seconds/60 if you need more precision.
My approach would be to use Calendar to make them Date
objects with the same day and then comparing them using for example timeIntervalSinceReferenceDate.
Another, cleaner (but most likely with more lines of resulting code) would be to create extension for Date
called secondsFromBeginningOfTheDay() -> TimeInterval
and then comparing the resulting double values.
Example based on the second approach:
// Creating Date from String
let textDate1 = "2017-01-13T12:21:00-0800"
let textDate2 = "2016-03-06T20:12:05-0900"
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZ"
formatter.timeZone = TimeZone.current
return formatter
} ()
// Dates used for the comparison
let date1 = dateFormatter.date(from: textDate1)
let date2 = dateFormatter.date(from: textDate2)
// Date extensions
extension Date {
func secondsFromBeginningOfTheDay() -> TimeInterval {
let calendar = Calendar.current
// omitting fractions of seconds for simplicity
let dateComponents = calendar.dateComponents([.hour, .minute, .second], from: self)
let dateSeconds = dateComponents.hour! * 3600 + dateComponents.minute! * 60 + dateComponents.second!
return TimeInterval(dateSeconds)
}
// Interval between two times of the day in seconds
func timeOfDayInterval(toDate date: Date) -> TimeInterval {
let date1Seconds = self.secondsFromBeginningOfTheDay()
let date2Seconds = date.secondsFromBeginningOfTheDay()
return date2Seconds - date1Seconds
}
}
if let date1 = date1, let date2 = date2 {
let diff = date1.timeOfDayInterval(toDate: date2)
// as text
if diff > 0 {
print("Time of the day in the second date is greater")
} else if diff < 0 {
print("Time of the day in the first date is greater")
} else {
print("Times of the day in both dates are equal")
}
// show interval as as H M S
let timeIntervalFormatter = DateComponentsFormatter()
timeIntervalFormatter.unitsStyle = .abbreviated
timeIntervalFormatter.allowedUnits = [.hour, .minute, .second]
print("Difference between times since midnight is", timeIntervalFormatter.string(from: diff) ?? "n/a")
}
// Output:
// Time of the day in the second date is greater
// Difference between times since midnight is 8h 51m 5s
Let say we got two dates in string format:
// "2017-01-13 11:40:17 +0000"
// "2016-03-15 10:22:14 +0000"
We need to convert this strings to Date format, we create DateFormatter() and set the format ("yyyy-MM-dd' 'HH:mm:ssZ") it gonna convert
//date formatter converts string to date in our case
let firstDateFormatter = DateFormatter()
firstDateFormatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ssZ"
Now we can get our date from string to Date format
//convert string to dates
if let date1 = firstDateFormatter.date(from: "2017-01-13 09:40:17 +0000"),
let date2 = firstDateFormatter.date(from: "2016-03-15 10:22:14 +0000") {
What we want is to compare only Hours and Minutes. So change dateformat to "HH:mm"
//we ve got the dates, now switch dateformat for other job
firstDateFormatter.dateFormat = "HH:mm"
Now get the string value from our date, that only contain "HH:mm"
// convert date to string ( part of string we want to compare )
let HHmmDate1 = firstDateFormatter.string(from: date1) //"17:40"
let HHmmDate2 = firstDateFormatter.string(from: date2) //"18:22"
Final step is to get date from our "HH:mm" values, let say we ask DateFormatter to give us a date, based on time only, in our case "17:40" and "18:22". DateFormatter will put some values for dates, so we get Jan 1, 2000 automatically for both dates, but it will get the time we provide.
//produce "default" dates with desired HH:mm
//default means same date, but time is different
let HH1 = firstDateFormatter.date(from: HHmmDate1) //"Jan 1, 2000 at 5:40 PM"
let HH2 = firstDateFormatter.date(from: HHmmDate2) //"Jan 1, 2000 at 6:22 PM"
Now we could easily compare dates
//compare
HH1! > HH2!
}
There are many options to compare dates with Calendar also
Much simpler than accepted answer:
SWIFT 4
// date1 and date2 are the dates you want to compare
let calendar = Calendar.current
var newDate = Date(TimeIntervalSinceReferenceDate: 0) // Initiates date at 2001-01-01 00:00:00 +0000
var newDate1 = Date(TimeIntervalSinceReferenceDate: 0) // Same as above
// Recieving the components from the dates you want to compare
let newDateComponents = calendar.dateComponents([.hour, .minute], from: date1)!
let newDate1Components = calendar.dateComponents([.hour, .minute], from: date2)!
// Adding those components
newDate = calendar.date(byAdding: newDateComponents, to: newDate)
newDate1 = calendar.date(byAdding: newDate1Components, to: newDate1)
This is very simple in Swift if you use Swifter Swift
date1.day = 1
date1.month = 1
date1.year = 2000
date2.day = 1
date2.month = 1
date2.year = 2000
now you can use >,<,== operators on date1 and date2 to compare just the time components.
edit - you could do this your self by extending the date class, for example swifter-swift does the bellow for the day component.
public var day: Int {
get {
return Calendar.current.component(.day, from: self)
}
set {
let allowedRange = Calendar.current.range(of: .day, in: .month, for: self)!
guard allowedRange.contains(newValue) else { return }
let currentDay = Calendar.current.component(.day, from: self)
let daysToAdd = newValue - currentDay
if let date = Calendar.current.date(byAdding: .day, value: daysToAdd, to: self) {
self = date
}
}
}