J'ai deux objets de date:
2017-01-13 11:40:17 +0000
2016-03-15 10:22:14 +0000
Je dois comparer juste l'heure de ces valeurs et ignorer la date
exemple: 12h00 et 12h01, 12h01 est plus tard donc (12h01> 12h00) == true
C'est l'itinéraire que j'ai suivi à la fin, ce qui facilite la comparaison de l'heure d'une date dans Swift
Heure du nouvel objet:
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
}
}
Extension de date pour un accès facile: // Ajoute la possibilité d'obtenir simplement l'heure d'une date:
extension Date {
var time: Time {
return Time(self)
}
}
Exemple:
let firstDate = Date()
let secondDate = firstDate
//Will return true
let timeEqual = firstDate.time == secondDate.time
Mon approche serait d'utiliser Calendar
pour en faire des objets Date
avec le même jour, puis de les comparer en utilisant par exemple timeIntervalSinceReferenceDate
.
Un autre, plus propre (mais très probablement avec plus de lignes de code résultant) serait de créer une extension pour Date
appelée secondsFromBeginningOfTheDay() -> TimeInterval
puis de comparer les valeurs doubles résultantes.
Exemple basé sur la deuxième approche:
// 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
J'ai eu un problème en faisant cela et je pense que j'ai trouvé une solution plus simple si vous voulez simplement comparer l'heure de deux dates. Il se sent un peu "hacky" mais semble bien fonctionner.
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)
Ma solution pour comparer deux heures de la journée en ignorant la 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!)
Vous pouvez maintenant comparer les entiers time1 et time2 sans tenir compte du jour. Vous pouvez ajouter les secondes/60 si vous avez besoin de plus de précision.
Il n'y a pas de type standard pour une heure du jour. Un type raisonnable pour commencer est juste un tuple:
typealias TimeOfDay = (hour: Int, minute: Int, second: Int)
Pour créer ces valeurs TimeOfDay
, vous aurez besoin d'un Calendar
. Par défaut, un Calendar
utilise le fuseau horaire du système à l'échelle du périphérique. Si vous ne le souhaitez pas, définissez explicitement le fuseau horaire de Calendar
. Exemple:
var calendar = Calendar.autoupdatingCurrent
calendar.timeZone = TimeZone(abbreviation: "UTC")!
Vous pouvez maintenant utiliser un DateFormatter
pour convertir les chaînes en Date
s (si nécessaire), puis utiliser calendar
pour extraire les composants de l'heure du Date
s:
let strings: [String] = ["2017-01-13 11:40:17 +0000", "2016-03-15 10:22:14 +0000"]
let parser = DateFormatter()
parser.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
let timesOfDay: [TimeOfDay] = strings.map({ (string) -> TimeOfDay in
let components = calendar.dateComponents([.hour, .minute, .second], from: parser.date(from: string)!)
return (hour: components.hour!, minute: components.minute!, second: components.second!)
})
Swift.print(timesOfDay)
// Output: [(11, 40, 17), (10, 22, 14)]
Enfin, vous pouvez comparer ces valeurs TimeOfDay
. Swift est livré avec des opérateurs de comparaison standard pour les tuples dont les éléments sont Comparable
, donc ce type TimeOfDay
est admissible. Vous pouvez simplement dire ceci:
if timesOfDay[0] < timesOfDay[1] {
Swift.print("date[0] comes first")
} else if timesOfDay[0] == timesOfDay[1] {
Swift.print("times are equal")
} else {
Swift.print("date[1] comes first")
}
C'est très simple dans Swift si vous utilisez Swifter Swift
date1.day = 1
date1.month = 1
date1.year = 2000
date2.day = 1
date2.month = 1
date2.year = 2000
vous pouvez maintenant utiliser les opérateurs>, <, == à date1 et date2 pour comparer uniquement les composants temporels.
modifier - vous pouvez le faire vous-même en étendant la classe de date, par exemple swifter-Swift fait le soufflet pour le composant jour.
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
}
}
}
Ce code fonctionne, vérifiez-le facilement dans la cour de récréation
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