La façon dont j'ai fait cela dans Swift 2.3 était:
let currentDate = NSDate()
let currentCalendar = NSCalendar.currentCalendar()
var startDate : NSDate?
var endDate : NSDate?
// The following two lines set the `startDate` and `endDate` to the start of the day
currentCalendar.rangeOfUnit(.Day, startDate: &startDate, interval: nil, forDate: currentDate)
currentCalendar.rangeOfUnit(.Day, startDate: &endDate, interval: nil, forDate: self)
let intervalComps = currentCalendar.components([.Day], fromDate: startDate!, toDate: endDate!, options: [])
print(intervalComps.day)
Maintenant, tout cela a changé avec Swift 3. Je dois soit utiliser NSCalendar
et NSDate
en tapant constamment le transtypage avec as
, soit trouver le moyen de le faire.
Quelle est la bonne façon de le faire dans Swift 3?
Il s'avère que c'est beaucoup plus simple à faire dans Swift 3:
extension Date {
func interval(ofComponent comp: Calendar.Component, fromDate date: Date) -> Int {
let currentCalendar = Calendar.current
guard let start = currentCalendar.ordinality(of: comp, in: .era, for: date) else { return 0 }
guard let end = currentCalendar.ordinality(of: comp, in: .era, for: self) else { return 0 }
return end - start
}
}
Modifier
La comparaison de l'ordinalité des deux dates doit se situer dans la même era
au lieu de la même year
, car les deux dates peuvent naturellement tomber dans des années différentes.
Utilisation
let yesterday = Date(timeInterval: -86400, since: Date())
let tomorrow = Date(timeInterval: 86400, since: Date())
let diff = tomorrow.interval(ofComponent: .day, fromDate: yesterday)
// return 2
Dans Swift 4 , il existe une simple ligne pour obtenir le nombre de jours (ou tout autre DateComponent) entre deux dates:
let diffInDays = Calendar.current.dateComponents([.day], from: dateA, to: dateB).day
Swift 4 Version
let startDate = "2000-11-22"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let formatedStartDate = dateFormatter.date(from: startDate)
let currentDate = Date()
let components = Set<Calendar.Component>([.second, .minute, .hour, .day, .month, .year])
let differenceOfDate = Calendar.current.dateComponents(components, from: formatedStartDate!, to: currentDate)
print (differenceOfDate)
Imprimé - Année: 16 mois: 10 jours: 19 heures: 12 minutes: 16 secondes: 42 isLeapMonth: false
Si quelqu'un veut le faire plus spécifiquement, suivez les étapes ci-dessous
1.Ajouter cette date extension
extension Date {
/// Returns the amount of years from another date
func years(from date: Date) -> Int {
return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
}
/// Returns the amount of months from another date
func months(from date: Date) -> Int {
return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
}
/// Returns the amount of weeks from another date
func weeks(from date: Date) -> Int {
return Calendar.current.dateComponents([.weekOfMonth], from: date, to: self).weekOfMonth ?? 0
}
/// Returns the amount of days from another date
func days(from date: Date) -> Int {
return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
}
/// Returns the amount of hours from another date
func hours(from date: Date) -> Int {
return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
}
/// Returns the amount of minutes from another date
func minutes(from date: Date) -> Int {
return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
}
/// Returns the amount of seconds from another date
func seconds(from date: Date) -> Int {
return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
}
/// Returns the amount of nanoseconds from another date
func nanoseconds(from date: Date) -> Int {
return Calendar.current.dateComponents([.nanosecond], from: date, to: self).nanosecond ?? 0
}
/// Returns the a custom time interval description from another date
func offset(from date: Date) -> String {
var result: String = ""
if years(from: date) > 0 { return "\(years(from: date))y" }
if months(from: date) > 0 { return "\(months(from: date))M" }
if weeks(from: date) > 0 { return "\(weeks(from: date))w" }
if seconds(from: date) > 0 { return "\(seconds(from: date))" }
if days(from: date) > 0 { result = result + " " + "\(days(from: date)) D" }
if hours(from: date) > 0 { result = result + " " + "\(hours(from: date)) H" }
if minutes(from: date) > 0 { result = result + " " + "\(minutes(from: date)) M" }
if seconds(from: date) > 0 { return "\(seconds(from: date))" }
return ""
}
}
2.Définissez-le globalement
fileprivate var timer: Timer?
3.Appelez cette méthode dans viewDidLoad ou où vous voulez
override func viewDidLoad() {
super.viewDidLoad()
self.getRemainingTime()
}
4.Utilisation
fileprivate func getRemainingTime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let startDate = "2018-06-02 10:11:12"
let currentDate = dateFormatter.string(from: Date())
if currentDate != startDate {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(calculateTime)), userInfo: nil, repeats: true)
RunLoop.current.add(timer!, forMode: RunLoopMode.commonModes)
timer?.fire()
}
else {
self.timer?.invalidate()
self.timer = nil
}
}
func calculateTime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let stdate : String = "2018-06-02 10:11:12"
let startDate = dateFormatter.date(from: stdate)!
let currentDate = Date()
let strTimer : String = startDate.offset(from: currentDate)
if !strTimer.isEmpty {
let stDay: String = "\((Int(strTimer)! % 31536000) / 86400)"
let stHour: String = "\((Int(strTimer)! % 86400) / 3600)"
let stMin: String = "\((Int(strTimer)! % 3600) / 60)"
let stSec: String = "\(Int(strTimer)! % 60)"
yourLabelOutlet.text = "Start In :\(stDay) Days \(stHour) Hours \(stMin) Minutes \(stSec) Seconds"
}
}
Fonctionne comme un charme Vous pouvez utiliser chaque chaîne distincte du côté de votre interface utilisateur,
Avec Swift4, vous pouvez facilement ne pas avoir de jours entre deux dates différentes en utilisant les codes ci-dessous.
Le premier est la différence en jours avec la date actuelle.
let previousDate = "2017-03-01"
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let previousDateFormated : Date? = dateFormatter.date(from: previousDate)
let difference = currentDate.timeIntervalSince(previousDateFormated!)
var differenceInDays = Int(difference/(60 * 60 * 24 ))
print(differenceInDays)
Continuez avec le code ci-dessus ... Ci-dessous, vous trouverez aucun nombre de jours pour deux dates différentes. le contenu de la date précédente est pris à partir de la date précédente
let futureDate = "2017-12-30"
let futureDateFormatted : Date? = dateFormatter.date(from: futureDate)
differenceInDays = (futureDateFormatted?.timeIntervalSince(previousDateFormated!))! / (60 * 60 * 24)
print(differenceInDays)
private func calculateDaysBetweenTwoDates(start: Date, end: Date) -> Int {
let currentCalendar = Calendar.current
guard let start = currentCalendar.ordinality(of: .day, in: .era, for: start) else {
return 0
}
guard let end = currentCalendar.ordinality(of: .day, in: .era, for: end) else {
return 0
}
return end - start
}
Si quelqu'un doit afficher toutes les unités de temps, par exemple "heures minutes secondes" et pas seulement "heures". Disons que la différence de temps entre deux dates est de 1 heure 59 minutes 20 secondes. Cette fonction affichera "1h 59m 20s".
Voici mon code:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'hh:mm:ss"
let start = dateFormatter.date(from: "2019-01-31T07:45:00")!
let end = dateFormatter.date(from: "2019-03-01T06:30:00")!
print("Date Difference : ", end.offsetFrom(date: start))
Définition de fonction:
extension Date {
func offsetFrom(date : Date) -> String {
let dayHourMinuteSecond: Set = [.day, .hour, .minute, .second]
let difference = NSCalendar.current.dateComponents(dayHourMinuteSecond, from: date, to: self);
let seconds = "\(difference.second ?? 0)s"
let minutes = "\(difference.minute ?? 0)m" + " " + seconds
let hours = "\(difference.hour ?? 0)h" + " " + minutes
let days = "\(difference.day ?? 0)d" + " " + hours
if let day = difference.day, day > 0 { return days }
if let hour = difference.hour, hour > 0 { return hours }
if let minute = difference.minute, minute > 0 { return minutes }
if let second = difference.second, second > 0 { return seconds }
return ""
}
}
private func days(actual day1:[Int],expect day2:[Int]) -> Int {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let first = "\(day1[2])-\(day1[1])-\(day1[0])"
let firstDate = dateFormatter.date(from:first)!
let last = "\(day2[2])-\(day2[1])-\(day2[0])"
let lastDate = dateFormatter.date(from:last)!
let currentCalendar = NSCalendar.current
let components = currentCalendar.dateComponents([.day], from: firstDate, to: lastDate)
return components.day!
}
Une autre approche à comparer avec les composantes jour-mois-année
Usage:
Entrez les dates au format suivant
[dd, mm, yyyy]
[9, 6, 2017]
[6, 6, 2017]
Mise à jour pour Swift 3:
si vous souhaitez imprimer le nombre de jours ainsi que la liste des jours entre deux dates de calendrier, utilisez ci-dessous le code simple;
// Déclaration de variable:
var daysListArray = [String]()
// fonction Defination:
func printCountBtnTwoDates(mStartDate: Date, mEndDate: Date) -> Int {
let calendar = Calendar.current
let formatter = DateFormatter()
var newDate = mStartDate
daysListArray.removeAll()
while newDate <= mEndDate {
formatter.dateFormat = "yyyy-MM-dd"
daysListArray.append(formatter.string(from: newDate))
newDate = calendar.date(byAdding: .day, value: 1, to: newDate)!
}
// print("daysListArray: \(daysListArray)") // if you want to print list between start date and end date
return daysListArray.count
}
// Pour appeler la fonction ci-dessus:
let count = self.printCountBtnTwoDates(mStartDate: your_start_date, mEndDate: your_end_date)
print("count: \(count)") // date count
// Profitez du codage ...!
J'ai trouvé ceci sur un autre fil, mais c'était finalement la solution la plus simple pour moi avec Swift 4:
let previousDate = ENTER DATE HERE
let now = Date()
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .brief // May delete the Word brief to let Xcode show you the other options
formatter.allowedUnits = [.month, .day, .hour]
formatter.maximumUnitCount = 1 // Show just one unit (i.e. 1d vs. 1d 6hrs)
let stringDate = formatter.string(from: previousDate, to: now)