web-dev-qa-db-fra.com

Swift 3 - Recherche le nombre de jours calendaires entre deux dates

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? 

33
Vinod Vishwanath

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
35
Vinod Vishwanath

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
65
flo_23

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

Swift4calendrierdate

15
Steve B

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,

9
iTALIYA

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)
6
Ashim Dahal
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
}
5
Kevin

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 ""
    }
}
1
Meet Doshi
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]
0
Anuj Panwar

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 ...!

0
Kiran jadhav

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)
0
Coltuxumab