webentwicklung-frage-antwort-db.com.de

Schnelle Tage zwischen zwei NSDates

Ich frage mich, ob es eine neue und großartige Möglichkeit gibt, die Anzahl der Tage zwischen zwei NSDates in Swift/dem "neuen" Kakao zu berechnen?

Z.B. wie in Ruby würde ich tun:

(end_date - start_date).to_i
79
Niko

Die akzeptierte Antwort gibt nicht die korrekte Tagesnummer zwischen zwei Datumsangaben zurück. Sie müssen auch den Zeitunterschied berücksichtigen. Wenn Sie beispielsweise die Datumsangaben 2015-01-01 10:00 und 2015-01-02 09:00 vergleichen, werden die Tage zwischen diesen Datumsangaben als 0 (Null) zurückgegeben, da die Differenz zwischen diesen Datumsangaben weniger als 24 Stunden (also 23 Stunden) beträgt.

Wenn Sie die genaue Tageszahl zwischen zwei Datumsangaben ermitteln möchten, können Sie dieses Problem folgendermaßen umgehen: 

// 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 und 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

Hier ist meine Antwort für 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

Ich sehe ein paar Swift3-Antworten, also füge ich meine hinzu:

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

Die Benennung fühlt sich schneller an, sie ist einzeilig und verwendet die neueste dateComponents()-Methode.

34
trevor-e

Ich habe meine Objective-C-Antwort übersetzt

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)

ergebnis 

<NSDateComponents: 0x10280a8a0>
     Day: 4

Das Schwierigste war, dass die Autovervollständigung ausDate und ToDate besteht und zwar NSDate?, aber tatsächlich müssen sie NSDate! sein, wie in der Referenz angegeben. 

Ich sehe nicht, wie eine gute Lösung mit einem Operator aussehen würde, da Sie die Einheit jeweils anders angeben möchten. Sie könnten das Zeitintervall zurückgeben, aber dann gewinnen Sie nicht viel.

29
vikingosegundo

Hier ist sehr schön, Date Erweiterung, um den Unterschied zwischen Datumsangaben in Jahren, Monaten, Tagen, Stunden, Minuten, Sekunden zu erhalten

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

Update für 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

Hier ist die Antwort für Swift 3 (getestet für IOS 10 Beta)

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

Dann kannst du es so nennen

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

Swift 3. Danke an Emin Buğra Saral oben für den startOfDay-Vorschlag.

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)!
    }
}

Verwendungszweck:

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

Die in Swift integrierten Dinge sind immer noch sehr einfach. Wie sollte es in diesem frühen Stadium sein. Sie können jedoch Ihr eigenes Material hinzufügen, mit dem Risiko, dass Operatoren und Funktionen für globale Domänen überladen werden. Sie sind jedoch lokal für Ihr Modul.

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

Hier ist meine Antwort für 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

Erins Methode auf Swift 3 aktualisiert. Dies zeigt Tage vom heutigen Tag (ohne Berücksichtigung der Tageszeit)

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

Ich werde meine Version hinzufügen, obwohl dieser Thread ein Jahr alt ist. Mein Code sieht so aus:

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

Ich hoffe es hilft jemandem.

Prost,

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

Dann benutze es wie

    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

Es gibt kaum eine Swift-spezifische Standardbibliothek. nur die schlanken numerischen, String- und Collection-Typen.

Es ist durchaus möglich, solche Abkürzungen mithilfe von Erweiterungen zu definieren, aber soweit es sich um die Standard-APIs handelt, gibt es keinen "neuen" Cocoa-Code. Schnelle Zuordnung direkt zu den gleichen alten verbose Cocoa-APIs, wie sie bereits vorhanden sind.

2
Wes Campaigne

Alle Antworten sind gut. Für Lokalisierungen müssen wir jedoch eine Anzahl Dezimaltage zwischen zwei Daten berechnen. So können wir das nachhaltige Dezimalformat bereitstellen.

// 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

eine einfachere Option wäre das Erstellen einer Erweiterung am Datum

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

Schnell 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

Schön handlicher Liner:

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

Swift 3 - Tage von heute bis zum Datum

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

Funktion so aufrufen

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

Sie können die folgende Erweiterung verwenden:

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
    }
}

Dann können Sie es so nennen:

startDate.daysTo(endDate)
0
Mauro García

Dies gibt eine absolute Differenz in Tagen zwischen einigen Date und heute zurück:

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

und dann verwenden Sie es:

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




}

wenn Sie Jahr, Monat, Tage und Stunden als Zeichenfolge benötigen, verwenden Sie diese Option 

var tomorrow = Calendar.current.date (byAdding: .day, Wert: 1, bis: Date ())!

let dc = tomorrow.completeOffset (von: Date ())

0
Akash Shindhe

Schnell 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