web-dev-qa-db-fra.com

Jours rapides entre deux NSDates

Je me demande s’il existe une possibilité nouvelle et impressionnante d’obtenir le nombre de jours entre deux NSDates à Swift/le "nouveau" cacao?

Par exemple. comme dans Ruby je ferais:

(end_date - start_date).to_i
79
Niko

La réponse acceptée ne renverra pas le numéro de jour correct entre deux dates. Vous devez également tenir compte de la différence de temps. Par exemple, si vous comparez les dates 2015-01-01 10:00 et 2015-01-02 09:00, les jours entre ces dates renverront 0 (zéro), car la différence entre ces dates est inférieure à 24 heures (23 heures).

Si votre objectif est d’obtenir le nombre exact de jours entre deux dates, vous pouvez résoudre ce problème comme suit: 

// Assuming that firstDate and secondDate are defined
// ...

let calendar = NSCalendar.currentCalendar()

// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDayForDate(firstDate)
let date2 = calendar.startOfDayForDate(secondDate)

let flags = NSCalendarUnit.Day
let components = calendar.components(flags, fromDate: date1, toDate: date2, options: [])

components.day  // This will return the number of day(s) between dates

Swift 3 et Swift 4 Version

let calendar = Calendar.current

// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: firstDate)
let date2 = calendar.startOfDay(for: secondDate)

let components = calendar.dateComponents([.day], from: date1, to: date2)
176
Emin Buğra Saral

Voici ma réponse pour Swift 2:

func daysBetweenDates(startDate: NSDate, endDate: NSDate) -> Int
{
    let calendar = NSCalendar.currentCalendar()

    let components = calendar.components([.Day], fromDate: startDate, toDate: endDate, options: [])

    return components.day
}
48
iphaaw

Je vois quelques réponses de Swift3 donc je vais ajouter les miennes:

public static func daysBetween(start: Date, end: Date) -> Int {
    return Calendar.current.dateComponents([.day], from: start, to: end).day!
}

Le nom se sent plus Swifty, c'est une ligne, et en utilisant la dernière méthode dateComponents().

34
trevor-e

J'ai traduit ma réponse Objective-C

let start = "2010-09-01"
let end = "2010-09-05"

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"

let startDate:NSDate = dateFormatter.dateFromString(start)
let endDate:NSDate = dateFormatter.dateFromString(end)

let cal = NSCalendar.currentCalendar()


let unit:NSCalendarUnit = .Day

let components = cal.components(unit, fromDate: startDate, toDate: endDate, options: nil)


println(components)

résultat 

<NSDateComponents: 0x10280a8a0>
     Day: 4

Le plus difficile était que l'auto-complétion insiste sur fromDate et toDate seraient NSDate?, mais en réalité, ils doivent être NSDate!, comme indiqué dans la référence. 

Je ne vois pas à quoi ressemblerait une bonne solution avec un opérateur, car vous souhaitez spécifier l'unité différemment dans chaque cas. Vous pouvez retourner l'intervalle de temps, mais vous ne gagnerez pas beaucoup.

29
vikingosegundo

Voici une très jolie extension Date pour obtenir la différence entre les dates en années, mois, jours, heures, minutes, secondes

extension Date {

    func years(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.year], from: sinceDate, to: self).year
    }

    func months(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.month], from: sinceDate, to: self).month
    }

    func days(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.day], from: sinceDate, to: self).day
    }

    func hours(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.hour], from: sinceDate, to: self).hour
    }

    func minutes(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.minute], from: sinceDate, to: self).minute
    }

    func seconds(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.second], from: sinceDate, to: self).second
    }

}
19
Krunal

Mise à jour pour Swift 3 iOS 10 Beta 4

func daysBetweenDates(startDate: Date, endDate: Date) -> Int {
    let calendar = Calendar.current
    let components = calendar.dateComponents([Calendar.Component.day], from: startDate, to: endDate)
    return components.day!
}
16
ChaosSpeeder

Voici la réponse pour Swift 3 (testé pour IOS 10 bêta)

func daysBetweenDates(startDate: Date, endDate: Date) -> Int
{
    let calendar = Calendar.current
    let components = calendar.components([.day], from: startDate, to: endDate, options: [])
    return components.day!
}

Ensuite, vous pouvez l'appeler comme ça

let pickedDate: Date = sender.date
let NumOfDays: Int = daysBetweenDates(startDate: pickedDate, endDate: Date())
    print("Num of Days: \(NumOfDays)")
8
kazantatar

Swift 3. Merci à Emin Buğra Saral ci-dessus pour la suggestion startOfDay.

extension Date {

    func daysBetween(date: Date) -> Int {
        return Date.daysBetween(start: self, end: date)
    }

    static func daysBetween(start: Date, end: Date) -> Int {
        let calendar = Calendar.current

        // Replace the hour (time) of both dates with 00:00
        let date1 = calendar.startOfDay(for: start)
        let date2 = calendar.startOfDay(for: end)

        let a = calendar.dateComponents([.day], from: date1, to: date2)
        return a.value(for: .day)!
    }
}

Usage:

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let start = dateFormatter.date(from: "2017-01-01")!
let end = dateFormatter.date(from: "2018-01-01")!

let diff = Date.daysBetween(start: start, end: end) // 365
7
Norman

Les choses construites dans Swift sont encore très basiques. Comme ils devraient être à ce stade précoce. Mais vous pouvez ajouter vos propres problèmes aux risques liés aux opérateurs surchargés et aux fonctions de domaine globales. Ils seront cependant locaux pour votre module.

let now = NSDate()
let seventies = NSDate(timeIntervalSince1970: 0)

// Standard solution still works
let days = NSCalendar.currentCalendar().components(.CalendarUnitDay, 
           fromDate: seventies, toDate: now, options: nil).day

// Flashy Swift... maybe...
func -(lhs:NSDate, rhs:NSDate) -> DateRange {
    return DateRange(startDate: rhs, endDate: lhs)
}

class DateRange {
    let startDate:NSDate
    let endDate:NSDate
    var calendar = NSCalendar.currentCalendar()
    var days: Int {
        return calendar.components(.CalendarUnitDay, 
               fromDate: startDate, toDate: endDate, options: nil).day
    }
    var months: Int {
        return calendar.components(.CalendarUnitMonth, 
               fromDate: startDate, toDate: endDate, options: nil).month
    }
    init(startDate:NSDate, endDate:NSDate) {
        self.startDate = startDate
        self.endDate = endDate
    }
}

// Now you can do this...
(now - seventies).months
(now - seventies).days
3
Daniel Schlaug

Voici ma réponse pour Swift 3:

func daysBetweenDates(startDate: NSDate, endDate: NSDate, inTimeZone timeZone: TimeZone? = nil) -> Int {
    var calendar = Calendar.current
    if let timeZone = timeZone {
        calendar.timeZone = timeZone
    }
    let dateComponents = calendar.dateComponents([.day], from: startDate.startOfDay, to: endDate.startOfDay)
    return dateComponents.day!
}
3
Alen Liang

La méthode d'Erin mise à jour en Swift 3

func daysBetweenDates( endDate: Date) -> Int 
    let calendar: Calendar = Calendar.current 
    let date1 = calendar.startOfDay(for: Date()) 
    let date2 = calendar.startOfDay(for: secondDate) 
    return calendar.dateComponents([.day], from: date1, to: date2).day! 
}
2
Peter Johnson

Je vais ajouter ma version même si ce fil a un an. Mon code ressemble à ceci:

    var name = txtName.stringValue // Get the users name

    // Get the date components from the window controls
    var dateComponents = NSDateComponents()
    dateComponents.day = txtDOBDay.integerValue
    dateComponents.month = txtDOBMonth.integerValue
    dateComponents.year = txtDOBYear.integerValue

    // Make a Gregorian calendar
    let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)

    // Get the two dates we need
    var birthdate = calendar?.dateFromComponents(dateComponents)
    let currentDate = NSDate()

    var durationDateComponents = calendar?.components(NSCalendarUnit.CalendarUnitDay, fromDate: birthdate!, toDate: currentDate, options: nil)

    let numberOfDaysAlive = durationDateComponents?.day

    println("\(numberOfDaysAlive!)")

    txtGreeting.stringValue = "Hello \(name), You have been alive for \(numberOfDaysAlive!) days."

J'espère que ça aide quelqu'un.

À votre santé,

2
Andrew H
extension Date {
    func daysFromToday() -> Int {
        return Calendar.current.dateComponents([.day], from: self, to: Date()).day!
    }
}

Alors utilisez-le comme

    func dayCount(dateString: String) -> String{
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMM dd,yyyy hh:mm a"
        let fetchedDate = dateFormatter.date(from: dateString)


        let day = fetchedDate?.daysFromToday()
        if day! > -1{
            return "\(day!) days passed."
        }else{
        return "\(day! * -1) days left."
        }
    }
2
Murad Al Wajed

Il n'y a pas encore de bibliothèque standard spécifique à Swift; juste les types numériques, de chaîne et de collection lean de base.

Il est parfaitement possible de définir de tels raccourcis à l'aide d'extensions, mais en ce qui concerne les API prêtes à l'emploi, il n'y a pas de "nouveau" Cocoa; Swift mappe directement les mêmes anciennes API de cacao telles qu'elles existent déjà.

2
Wes Campaigne

Toute réponse est bonne. Mais pour les localisations, nous devons calculer un nombre de jours décimaux entre deux dates. afin que nous puissions fournir le format décimal durable.

// This method returns the fractional number of days between to dates
func getFractionalDaysBetweenDates(date1: Date, date2: Date) -> Double {

    let components = Calendar.current.dateComponents([.day, .hour], from: date1, to: date2)

    var decimalDays = Double(components.day!)
    decimalDays += Double(components.hour!) / 24.0

    return decimalDays
}
1
Durul Dalkanat

option plus facile serait de créer une extension sur Date

public extension Date {

        public var currentCalendar: Calendar {
            return Calendar.autoupdatingCurrent
        }

        public func daysBetween(_ date: Date) -> Int {
            let components = currentCalendar.dateComponents([.day], from: self, to: date)
            return components.day!
        }
    }
0
Suhit Patil

Swift 3.2

extension DateComponentsFormatter {
    func difference(from fromDate: Date, to toDate: Date) -> String? {
        self.allowedUnits = [.year,.month,.weekOfMonth,.day]
        self.maximumUnitCount = 1
        self.unitsStyle = .full
        return self.string(from: fromDate, to: toDate)
    }
}
0
Adam Smaka

Beau manchon one liner:

extension Date {
  var daysFromNow: Int {
    return Calendar.current.dateComponents([.day], from: Date(), to: self).day!
  }
}
0
Rom.

Swift 3 - Jours à compter d'aujourd'hui jusqu'à la date

func daysUntilDate(endDateComponents: DateComponents) -> Int
    {
        let cal = Calendar.current
        var components = cal.dateComponents([.era, .year, .month, .day], from: NSDate() as Date)
        let today = cal.date(from: components)
        let otherDate = cal.date(from: endDateComponents)

        components = cal.dateComponents([Calendar.Component.day], from: (today! as Date), to: otherDate!)
        return components.day!
    }

Fonction d'appel comme celle-ci

// Days from today until date
   var examnDate = DateComponents()
   examnDate.year = 2016
   examnDate.month = 12
   examnDate.day = 15
   let daysCount = daysUntilDate(endDateComponents: examnDate)
0
karenms

Vous pouvez utiliser l'extension suivante:

public extension Date {
    func daysTo(_ date: Date) -> Int? {
        let calendar = Calendar.current

        // Replace the hour (time) of both dates with 00:00
        let date1 = calendar.startOfDay(for: self)
        let date2 = calendar.startOfDay(for: date)

        let components = calendar.dateComponents([.day], from: date1, to: date2)
        return components.day  // This will return the number of day(s) between dates
    }
}

Ensuite, vous pouvez l'appeler comme ceci:

startDate.daysTo(endDate)
0
Mauro García

Cela renvoie une différence absolue en jours entre certains Date et aujourd'hui:

extension Date {
  func daysFromToday() -> Int {
    return abs(Calendar.current.dateComponents([.day], from: self, to: Date()).day!)
  }
}

et ensuite l'utiliser:

if someDate.daysFromToday() >= 7 {
  // at least a week from today
}
0
budidino
  func completeOffset(from date:Date) -> String? {

    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .brief

    return  formatter.string(from: Calendar.current.dateComponents([.year,.month,.day,.hour,.minute,.second], from: date, to: self))




}

si vous avez besoin d’année mois jours et heures comme chaîne utilisez cette 

var demain = Calendar.current.date (byAdding: .day, valeur: 1, to: Date ())!

let dc = tomorrow.completeOffset (à partir de: Date ())

0
Akash Shindhe

Swift 4

 func getDateHeader(indexPath: Int) -> String {
    let formatter2 = DateFormatter()
    formatter2.dateFormat = "MM-dd-yyyy"
    var dateDeadline : Date?

    dateDeadline = formatter2.date(from: arrCompletedDate[indexPath] as! String)

    let currentTime = dateDeadline?.unixTimestamp
    let calendar = NSCalendar.current

    let date = NSDate(timeIntervalSince1970: Double(currentTime!))
    if calendar.isDateInYesterday(date as Date) { return "Yesterday" }
    else if calendar.isDateInToday(date as Date) { return "Today" }
    else if calendar.isDateInTomorrow(date as Date) { return "Tomorrow" }
    else {
        let startOfNow = calendar.startOfDay(for: NSDate() as Date)
        let startOfTimeStamp = calendar.startOfDay(for: date as Date)
        let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
        let day = components.day!
        if day < 1 { return "\(abs(day)) days ago" }
        else { return "In \(day) days" }
    }
}
0
Niraj Paul