Ermitteln der Differenz zwischen zwei NSDates in (Monate / Tage / Stunden / Minuten / Sekunden)


206

Ich versuche, die Differenz zwischen dem aktuellen Datum als NSDate()und einem Datum aus einem PHP- time();Aufruf zu ermitteln, zum Beispiel : NSDate(timeIntervalSinceReferenceDate: 1417147270). Wie kann ich den Zeitunterschied zwischen den beiden Daten ermitteln? Ich hätte gerne eine Funktion, die die beiden Daten vergleicht und if(seconds > 60)dann Minuten, if(minutes > 60)Stunden und zurückgibtif(hours > 24) Tage und so weiter.

Wie soll ich das machen?

EDIT: Die aktuell akzeptierte Antwort hat genau das getan, was ich tun wollte. Ich empfehle es zur einfachen Verwendung, um die Zeit zwischen zwei Daten in der von der PHP- time()Funktion verwendeten Form abzurufen . Wenn Sie mit PHP nicht besonders vertraut sind, ist dies die Zeit in Sekunden ab dem 1. Januar 1970. Dies ist für ein Backend in PHP von Vorteil. Wenn Sie möglicherweise ein Backend wie NodeJS verwenden, sollten Sie einige der anderen Optionen in Betracht ziehen, die Sie unten finden.


2
Mir ist klar, dass dies etwas alt ist, aber was haben Sie mit dem Unterschied vor? Wenn Sie beispielsweise eine Zeichenfolge für den Benutzer formatieren möchten, sollten Sie diese verwenden NSDateComponentsFormatter. Es ist sehr konfigurierbar, sodass Sie entsprechend knappe Ergebnisse erzielen können (z .maximumUnitCount = 1. B. ).
Ken Thomases

Wirklich, die Frage, was Sie vorhaben, ist absolut notwendig. Bedenken Sie, dass ein Monat nur 28 Tage oder 31 Tage plus eine Stunde betragen kann.
Gnasher729

Antworten:


510

Xcode 8.3 • Swift 3.1 oder höher

Mithilfe des Kalenders können Sie eine Erweiterung erstellen, mit der Sie Ihre Datumsberechnungen wie folgt durchführen können:

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 a custom time interval description from another date
    func offset(from date: Date) -> 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 days(from: date)    > 0 { return "\(days(from: date))d"    }
        if hours(from: date)   > 0 { return "\(hours(from: date))h"   }
        if minutes(from: date) > 0 { return "\(minutes(from: date))m" }
        if seconds(from: date) > 0 { return "\(seconds(from: date))s" }
        return ""
    }
}

Verwenden des Formatierers für Datumskomponenten

let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.allowedUnits = [.year,.month,.weekOfMonth,.day,.hour,.minute,.second]
dateComponentsFormatter.maximumUnitCount = 1
dateComponentsFormatter.unitsStyle = .full
dateComponentsFormatter.string(from: Date(), to: Date(timeIntervalSinceNow: 4000000))  // "1 month"

let date1 = DateComponents(calendar: .current, year: 2014, month: 11, day: 28, hour: 5, minute: 9).date!
let date2 = DateComponents(calendar: .current, year: 2015, month: 8, day: 28, hour: 5, minute: 9).date!

let years = date2.years(from: date1)     // 0
let months = date2.months(from: date1)   // 9
let weeks = date2.weeks(from: date1)     // 39
let days = date2.days(from: date1)       // 273
let hours = date2.hours(from: date1)     // 6,553
let minutes = date2.minutes(from: date1) // 393,180
let seconds = date2.seconds(from: date1) // 23,590,800

let timeOffset = date2.offset(from: date1) // "9M"

let date3 = DateComponents(calendar: .current, year: 2014, month: 11, day: 28, hour: 5, minute: 9).date!
let date4 = DateComponents(calendar: .current, year: 2015, month: 11, day: 28, hour: 5, minute: 9).date!

let timeOffset2 = date4.offset(from: date3) // "1y"

let date5 = DateComponents(calendar: .current, year: 2017, month: 4, day: 28).date!
let now = Date()
let timeOffset3 = now.offset(from: date5) // "1w"

1
Gibt in Swift 2.0 .CalendarUnitSecondFehler 'NSCalendarUnit.Type' does not have a member named 'CalendarUnitSecond', wissen Sie, wie man es löst?
Matte.Car

2
@ Matte.Car müssen Sie .Second verwenden und anstelle von Optionen: Null müssen Sie Optionen verwenden: []. Sie können einen Blick auf meine Bearbeitung werfen.
Leo Dabus

1
Ich hasse die Vervielfältigungen in dieser Antwort, würde ich eine Methode basierend auf NSCalendarUnit, implementiert als return Calendar.current().components(unit, from: date, to: self, options: [])?. valueForComponent(unit)(auf iOS> 8).
Sulthan

4
Da die Antwort mit DateComponentsFormatterSO viel besser ist als auf lange Sicht, sollte dies wirklich ganz oben auf der Antwort stehen.
rmaddy

1
Du bist absolut unglaublich! Diese Erweiterung hat mir sehr geholfen!
Marian Petrisor

45

Wenn jemand alle Zeiteinheiten anzeigen muss, z. B. "Stunden Minuten Sekunden", nicht nur "Stunden". Angenommen, der Zeitunterschied zwischen zwei Daten beträgt 1 Stunde 59 Minuten 20 Sekunden. Diese Funktion zeigt "1h 59m 20s" an.

Hier ist mein Objective-C-Code:

extension NSDate {

    func offsetFrom(date: NSDate) -> String {

        let dayHourMinuteSecond: NSCalendarUnit = [.Day, .Hour, .Minute, .Second]
        let difference = NSCalendar.currentCalendar().components(dayHourMinuteSecond, fromDate: date, toDate: self, options: [])

        let seconds = "\(difference.second)s"
        let minutes = "\(difference.minute)m" + " " + seconds
        let hours = "\(difference.hour)h" + " " + minutes
        let days = "\(difference.day)d" + " " + hours

        if difference.day    > 0 { return days }
        if difference.hour   > 0 { return hours }
        if difference.minute > 0 { return minutes }
        if difference.second > 0 { return seconds }
        return ""
    }

}

In Swift 3+:

extension Date {

    func offsetFrom(date: Date) -> String {

        let dayHourMinuteSecond: Set<Calendar.Component> = [.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 ""
    }

}

3
Das ist genau das, was ich brauche. einfach und erledigt den Job.
Chen Li Yong

14

Du fragst:

Ich hätte gerne eine Funktion, die die beiden Daten vergleicht und wenn (Sekunden> 60) dann Minuten zurückgibt, wenn (Minuten> 60) Stunden zurückgeben und wenn (Stunden> 24) Tage zurückgeben und so weiter.

Ich gehe davon aus, dass Sie versuchen, eine Zeichenfolgendarstellung der zwischen zwei Daten verstrichenen Zeit zu erstellen. Anstatt dafür Ihren eigenen Code zu schreiben, hat Apple bereits eine Klasse, die genau dafür ausgelegt ist. Das heißt, die Verwendung DateComponentsFormatter, eingestellt allowedUnits, was auch immer Wert Sinn , um Ihre Anwendung zu machen, setzen unitsStyle, was auch immer Sie wollen (zB .full), und dann rufen string(from:to:).

ZB in Swift 3:

let previousDate = ...
let now = Date()

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [.month, .day, .hour, .minute, .second]
formatter.maximumUnitCount = 2   // often, you don't care about seconds if the elapsed time is in months, so you'll set max unit to whatever is appropriate in your case

let string = formatter.string(from: previousDate, to: now)

Dadurch wird auch die für das betreffende Gerät geeignete Zeichenfolge lokalisiert.

Oder in Swift 2.3:

let previousDate = ...
let now = NSDate()

let formatter = NSDateComponentsFormatter()
formatter.unitsStyle = .Full
formatter.allowedUnits = [.Month, .Day, .Hour, .Minute, .Second]
formatter.maximumUnitCount = 2

let string = formatter.stringFromDate(previousDate, toDate: now)

Wenn Sie nach den tatsächlichen numerischen Werten suchen, verwenden Sie einfach dateComponents. ZB in Swift 3:

let components = Calendar.current.dateComponents([.month, .day, .hour, .minute, .second], from: previousDate, to: now)

Oder in Swift 2.3:

let components = NSCalendar.currentCalendar().components([.Month, .Day, .Hour, .Minute, .Second], fromDate: previousDate, toDate: now, options: [])

6

kombinierte Erweiterung + DateComponentsFormatter aus der Antwort von @ leo-dabus

Xcode 8.3 • Swift 3.1

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

let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.difference(from: Date(), to: Date(timeIntervalSinceNow: 4000000)) // "1 month"

4
   func dateDiff(dateStr:String) -> String {
            var f:NSDateFormatter = NSDateFormatter()
            f.timeZone = NSTimeZone.localTimeZone()
            f.dateFormat = "yyyy-M-dd'T'HH:mm:ss.SSSZZZ"

            var now = f.stringFromDate(NSDate())
            var startDate = f.dateFromString(dateStr)
            var endDate = f.dateFromString(now)
            var calendar: NSCalendar = NSCalendar.currentCalendar()

            let calendarUnits = NSCalendarUnit.CalendarUnitWeekOfMonth | NSCalendarUnit.CalendarUnitDay | NSCalendarUnit.CalendarUnitHour | NSCalendarUnit.CalendarUnitMinute | NSCalendarUnit.CalendarUnitSecond
            let dateComponents = calendar.components(calendarUnits, fromDate: startDate!, toDate: endDate!, options: nil)

            let weeks = abs(dateComponents.weekOfMonth)
            let days = abs(dateComponents.day)
            let hours = abs(dateComponents.hour)
            let min = abs(dateComponents.minute)
            let sec = abs(dateComponents.second)

            var timeAgo = ""

            if (sec > 0){
                if (sec > 1) {
                    timeAgo = "\(sec) Seconds Ago"
                } else {
                    timeAgo = "\(sec) Second Ago"
                }
            }

            if (min > 0){
                if (min > 1) {
                    timeAgo = "\(min) Minutes Ago"
                } else {
                    timeAgo = "\(min) Minute Ago"
                }
            }

            if(hours > 0){
                if (hours > 1) {
                    timeAgo = "\(hours) Hours Ago"
                } else {
                    timeAgo = "\(hours) Hour Ago"
                }
            }

            if (days > 0) {
                if (days > 1) {
                    timeAgo = "\(days) Days Ago"
                } else {
                    timeAgo = "\(days) Day Ago"
                }
            }

            if(weeks > 0){
                if (weeks > 1) {
                    timeAgo = "\(weeks) Weeks Ago"
                } else {
                    timeAgo = "\(weeks) Week Ago"
                }
            }

            print("timeAgo is===> \(timeAgo)")
            return timeAgo;
        }

Versuchen Sie, den Datumsformatierer zu laden, und eine noch bessere Option wäre, ihn statisch zu machen
Summersign vom

4

Ich habe Leo Dabus 'Antwort eine "lange" Version hinzugefügt, falls Sie eine Zeichenfolge haben möchten, die so etwas wie "vor 2 Wochen" anstelle von "2w" sagt ...

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([.weekOfYear], from: date, to: self).weekOfYear ?? 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 a custom time interval description from another date
    func offset(from date: Date) -> 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 days(from: date)    > 0 { return "\(days(from: date))d"    }
        if hours(from: date)   > 0 { return "\(hours(from: date))h"   }
        if minutes(from: date) > 0 { return "\(minutes(from: date))m" }
        if seconds(from: date) > 0 { return "\(seconds(from: date))s" }
        return ""
    }

    func offsetLong(from date: Date) -> String {
        if years(from: date)   > 0 { return years(from: date) > 1 ? "\(years(from: date)) years ago" : "\(years(from: date)) year ago" }
        if months(from: date)  > 0 { return months(from: date) > 1 ? "\(months(from: date)) months ago" : "\(months(from: date)) month ago" }
        if weeks(from: date)   > 0 { return weeks(from: date) > 1 ? "\(weeks(from: date)) weeks ago" : "\(weeks(from: date)) week ago"   }
        if days(from: date)    > 0 { return days(from: date) > 1 ? "\(days(from: date)) days ago" : "\(days(from: date)) day ago" }
        if hours(from: date)   > 0 { return hours(from: date) > 1 ? "\(hours(from: date)) hours ago" : "\(hours(from: date)) hour ago"   }
        if minutes(from: date) > 0 { return minutes(from: date) > 1 ? "\(minutes(from: date)) minutes ago" : "\(minutes(from: date)) minute ago" }
        if seconds(from: date) > 0 { return seconds(from: date) > 1 ? "\(seconds(from: date)) seconds ago" : "\(seconds(from: date)) second ago" }
        return ""
    }

}

4

-> Verwenden Sie diese Option, um die Zeitlücke zwischen zwei Daten in Swift (mit zwei Zeichenfolgen) zu ermitteln.

func timeGapBetweenDates(previousDate : String,currentDate : String)
{
    let dateString1 = previousDate
    let dateString2 = currentDate

    let Dateformatter = DateFormatter()
    Dateformatter.dateFormat = "yyyy-MM-dd HH:mm:ss"


    let date1 = Dateformatter.date(from: dateString1)
    let date2 = Dateformatter.date(from: dateString2)


    let distanceBetweenDates: TimeInterval? = date2?.timeIntervalSince(date1!)
    let secondsInAnHour: Double = 3600
    let minsInAnHour: Double = 60
    let secondsInDays: Double = 86400
    let secondsInWeek: Double = 604800
    let secondsInMonths : Double = 2592000
    let secondsInYears : Double = 31104000

    let minBetweenDates = Int((distanceBetweenDates! / minsInAnHour))
    let hoursBetweenDates = Int((distanceBetweenDates! / secondsInAnHour))
    let daysBetweenDates = Int((distanceBetweenDates! / secondsInDays))
    let weekBetweenDates = Int((distanceBetweenDates! / secondsInWeek))
    let monthsbetweenDates = Int((distanceBetweenDates! / secondsInMonths))
    let yearbetweenDates = Int((distanceBetweenDates! / secondsInYears))
    let secbetweenDates = Int(distanceBetweenDates!)




    if yearbetweenDates > 0
    {
        print(yearbetweenDates,"years")//0 years
    }
    else if monthsbetweenDates > 0
    {
        print(monthsbetweenDates,"months")//0 months
    }
    else if weekBetweenDates > 0
    {
        print(weekBetweenDates,"weeks")//0 weeks
    }
    else if daysBetweenDates > 0
    {
        print(daysBetweenDates,"days")//5 days
    }
    else if hoursBetweenDates > 0
    {
        print(hoursBetweenDates,"hours")//120 hours
    }
    else if minBetweenDates > 0
    {
        print(minBetweenDates,"minutes")//7200 minutes
    }
    else if secbetweenDates > 0
    {
        print(secbetweenDates,"seconds")//seconds
    }
}

3

Leicht modifizierter Code für Swift 3.0

let calendar = NSCalendar.current as NSCalendar

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

let flags = NSCalendar.Unit.day
let components = calendar.components(flags, from: date1, to: date2, options: [])

return components.day!


1

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

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

var calendar: NSCalendar = 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.DayCalendarUnit
let components = calendar.components(flags, fromDate: date1, toDate: date2, options: nil)

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

1

Mit Swift 3 können Sie je nach Bedarf eine der beiden folgenden Möglichkeiten wählen, um Ihr Problem zu lösen.


1. Zeigen Sie dem Benutzer die Differenz zwischen zwei Daten an

Mit a können Sie DateComponentsFormatterZeichenfolgen für die Benutzeroberfläche Ihrer App erstellen. DateComponentsFormatterhat eine maximumUnitCountEigenschaft mit der folgenden Deklaration:

var maximumUnitCount: Int { get set }

Verwenden Sie diese Eigenschaft, um die Anzahl der Einheiten zu begrenzen, die in der resultierenden Zeichenfolge angezeigt werden. Wenn diese Eigenschaft beispielsweise auf 2 gesetzt ist, lautet die resultierende Zeichenfolge anstelle von "1h 10m, 30s" "1h 10m". Verwenden Sie diese Eigenschaft, wenn Sie Platzmangel haben oder Werte auf die nächste große Einheit aufrunden möchten.

Wenn Sie den maximumUnitCountWert auf setzen 1, wird garantiert, dass der Unterschied nur in einem angezeigt wirdDateComponentsFormatter Einheit (Jahre, Monate, Tage, Stunden oder Minuten).

Der folgende Spielplatzcode zeigt, wie der Unterschied zwischen zwei Daten angezeigt wird:

import Foundation

let oldDate = Date(timeIntervalSinceReferenceDate: -16200)
let newDate = Date(timeIntervalSinceReferenceDate: 0)

let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.allowedUnits = [NSCalendar.Unit.year, .month, .day, .hour, .minute]
dateComponentsFormatter.maximumUnitCount = 1
dateComponentsFormatter.unitsStyle = DateComponentsFormatter.UnitsStyle.full
let timeDifference = dateComponentsFormatter.string(from: oldDate, to: newDate)

print(String(reflecting: timeDifference)) // prints Optional("5 hours")

Beachten Sie, dass DateComponentsFormatterdas Ergebnis aufgerundet wird. Daher wird eine Differenz von 4 Stunden und 30 Minuten als 5 Stunden angezeigt .

Wenn Sie diesen Vorgang wiederholen müssen, können Sie Ihren Code umgestalten:

import Foundation

struct Formatters {

    static let dateComponentsFormatter: DateComponentsFormatter = {
        let dateComponentsFormatter = DateComponentsFormatter()
        dateComponentsFormatter.allowedUnits = [NSCalendar.Unit.year, .month, .day, .hour, .minute]
        dateComponentsFormatter.maximumUnitCount = 1
        dateComponentsFormatter.unitsStyle = DateComponentsFormatter.UnitsStyle.full
        return dateComponentsFormatter
    }()

}

extension Date {
    
    func offset(from: Date) -> String? {
        return Formatters.dateComponentsFormatter.string(from: oldDate, to: self)
    }
    
}

let oldDate = Date(timeIntervalSinceReferenceDate: -16200)
let newDate = Date(timeIntervalSinceReferenceDate: 0)

let timeDifference = newDate.offset(from: oldDate)
print(String(reflecting: timeDifference)) // prints Optional("5 hours")

2. Ermitteln Sie den Unterschied zwischen zwei Daten ohne Formatierung

Wenn Sie dem Benutzer den Unterschied zwischen zwei Daten nicht formatieren müssen, können Sie ihn verwenden Calendar. Calendarhat eine Methode dateComponents(_:from:to:)mit der folgenden Deklaration:

func dateComponents(_ components: Set<Calendar.Component>, from start: Date, to end: Date) -> DateComponents

Gibt die Differenz zwischen zwei Daten zurück.

Der unten verwendete Spielplatzcode dateComponents(_:from:to:)zeigt, wie Sie die Differenz zwischen zwei Daten abrufen können, indem Sie die Differenz in nur einem Typ Calendar.Component(Jahre, Monate, Tage, Stunden oder Minuten) zurückgeben.

import Foundation

let oldDate = Date(timeIntervalSinceReferenceDate: -16200)
let newDate = Date(timeIntervalSinceReferenceDate: 0)

let descendingOrderedComponents = [Calendar.Component.year, .month, .day, .hour, .minute]
let dateComponents = Calendar.current.dateComponents(Set(descendingOrderedComponents), from: oldDate, to: newDate)
let arrayOfTuples = descendingOrderedComponents.map { ($0, dateComponents.value(for: $0)) }

for (component, value) in arrayOfTuples {
    if let value = value, value > 0 {
        print(component, value) // prints hour 4
        break
    }
}

Wenn Sie diesen Vorgang wiederholen müssen, können Sie Ihren Code umgestalten:

import Foundation

extension Date {
    
    func offset(from: Date) -> (Calendar.Component, Int)? {
        let descendingOrderedComponents = [Calendar.Component.year, .month, .day, .hour, .minute]
        let dateComponents = Calendar.current.dateComponents(Set(descendingOrderedComponents), from: from, to: self)
        let arrayOfTuples = descendingOrderedComponents.map { ($0, dateComponents.value(for: $0)) }
        
        for (component, value) in arrayOfTuples {
            if let value = value, value > 0 {
                return (component, value)
            }
        }
        
        return nil
    }

}

let oldDate = Date(timeIntervalSinceReferenceDate: -16200)
let newDate = Date(timeIntervalSinceReferenceDate: 0)

if let (component, value) = newDate.offset(from: oldDate) {
    print(component, value) // prints hour 4
}

1

In Swift 2.2

    /// Returns the amount of years from another date
func years(fromdate: NSDate) -> Int {
    return NSCalendar.currentCalendar().components([.Year], fromDate: fromdate, toDate: NSDate(), options: []).year ?? 0
}
/// Returns the amount of months from another date
func months(fromdate: NSDate) -> Int {
    return NSCalendar.currentCalendar().components([.Month], fromDate: fromdate, toDate: NSDate(), options: []).month ?? 0
}
/// Returns the amount of weeks from another date
func weeks(fromdate: NSDate) -> Int {
    return NSCalendar.currentCalendar().components([.WeekOfYear], fromDate: fromdate, toDate: NSDate(), options: []).weekOfYear ?? 0
}
/// Returns the amount of days from another date
func days(fromdate: NSDate) -> Int {
    return NSCalendar.currentCalendar().components([.Day], fromDate: fromdate, toDate: NSDate(), options: []).day ?? 0
}
/// Returns the amount of hours from another date
func hours(fromdate: NSDate) -> Int {
    return NSCalendar.currentCalendar().components([.Hour], fromDate: fromdate, toDate: NSDate(), options: []).hour ?? 0
}
/// Returns the amount of minutes from another date
func minutes(fromdate: NSDate) -> Int {
    return NSCalendar.currentCalendar().components([.Minute], fromDate: fromdate, toDate: NSDate(), options: []).minute ?? 0
}
/// Returns the amount of seconds from another date
func seconds(fromdate: NSDate) -> Int {
    return NSCalendar.currentCalendar().components(.Second, fromDate: fromdate, toDate: NSDate(), options: []).second ?? 0
}

1

Eine kleine Ergänzung zu Leo Dabus 'Antwort, um die Pluralversionen bereitzustellen und menschlicher lesbar zu sein.

Swift 3

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 a custom time interval description from another date
    func offset(from date: Date) -> String {
        if years(from: date)   == 1 { return "\(years(from: date)) year"   } else if years(from: date)   > 1 { return "\(years(from: date)) years"   }
        if months(from: date)  == 1 { return "\(months(from: date)) month"  } else if months(from: date)  > 1 { return "\(months(from: date)) month"  }
        if weeks(from: date)   == 1 { return "\(weeks(from: date)) week"   } else if weeks(from: date)   > 1 { return "\(weeks(from: date)) weeks"   }
        if days(from: date)    == 1 { return "\(days(from: date)) day"    } else if days(from: date)    > 1 { return "\(days(from: date)) days"    }
        if hours(from: date)   == 1 { return "\(hours(from: date)) hour"   } else if hours(from: date)   > 1 { return "\(hours(from: date)) hours"   }
        if minutes(from: date) == 1 { return "\(minutes(from: date)) minute" } else if minutes(from: date) > 1 { return "\(minutes(from: date)) minutes" }
        return ""
    }
}

0

Dies ist die kürzere Version: Grundsätzlich versuche ich, den Unterschied zwischen dem Post-Zeitstempel und dem Date()Jetzt zu ermitteln.

// MARK: - UPDATE Time Stamp
static func updateTimeStampPost(postTimeStamp: Date?, _ completion: (_ finalString: String?) -> Void) {
    // date in the current state
    let date = Date()
    let dateComponentFormatter = DateComponentsFormatter()

    // change the styling date, wether second minute or hour
    dateComponentFormatter.unitsStyle = .abbreviated
    dateComponentFormatter.allowedUnits = [.second, .minute, .hour, .day, .weekOfMonth]
    dateComponentFormatter.maximumUnitCount = 1

    // return the date new format as a string in the completion
    completion(dateComponentFormatter.string(from: postTimeStamp!, to: date))
}

0

Hier ist meine Antwort auf die obigen Swift 3-Antworten. Dies ist ab November 2016 aktuell. Die Xcode-Version war 8.2 Beta (8C23). Verwendete einige der oben genannten Vorschläge von Sagar und Emin und musste manchmal Xcode automatisch vervollständigen lassen, um die Syntax vorzuschlagen. Es schien, als hätte sich die Syntax wirklich auf diese Beta-Version geändert. buyDateIch habe von einem DatePicker bekommen:

let calendar = NSCalendar.current as NSCalendar
let currentDate = Date()
let date1 = calendar.startOfDay(for: buyDate!)
let date2 = calendar.startOfDay(for: currentDate)      
let flags = NSCalendar.Unit.day
let components = calendar.components(flags, from: date1, to: date2)
NSLog(" day= \(components.day)")

Entschuldigung, jetzt wo ich mir das ansehe, ist dies Sagars Lösung. Ich habe so viele Iterationen gemacht und so viele Dinge ausprobiert, dass ich dachte, es hätte sich geändert. Emins Lösung funktioniert nicht für den neuesten Swift 3.
RenaissanceMan

Sie sollten NSCalendarSwift 3 nicht wirklich verwenden Calendar. Das ist also vereinfacht let calendar = Calendar.current. Und dann componentswürde aussehen wie : let components = calendar.dateComponents([.day], from: date1, to: date2).
Rob

0

Für XCode Version 8.3.3 und Swift 3.0:

    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .medium
    dateFormatter.timeStyle = .short

    var beginDate = "2017-08-24 12:00:00"
    var endDate = "2017-09-07 12:00:00"


    let startDateTime = dateFormatter.date(from: beginDate) //according to date format your date string
    print(startDateTime ?? "") //Convert String to Date

    let endDateTime = dateFormatter.date(from: endDate) //according to date format your date string
    print(endDateTime ?? "") //Convert String to Date

    let dateComponentsFormatter = DateComponentsFormatter()
    dateComponentsFormatter.allowedUnits = [NSCalendar.Unit.minute,NSCalendar.Unit.hour,NSCalendar.Unit.day]


   let interval = endDateTime!.timeIntervalSince(startDateTime!)
   var diff = dateComponentsFormatter.string(from: interval)!

   print(diff)

   var day_i  = 0
   var hour_i = 0
   var min_i = 0


     if (diff.contains("d"))
       {
              let day = diff.substring(to: (diff.range(of: "d")?.lowerBound)!)

               day_i  = Int(day)!
               print ("day --> \(day_i)")

               diff = diff.substring(from:(diff.range(of : " ")?.upperBound )!)
               print(diff)
       }


       let hour = diff.substring(to: (diff.range(of : ":")?.lowerBound )!)
       hour_i  = Int(hour)!
       print ("hour --> \(hour_i)")

       let min = diff.substring(from: (diff.range(of : ":")?.upperBound )!)
       min_i  = Int(min)!
       print ("min --> \(min_i)")

0

Einige Ergänzungen in jose920405 antworten, um es mit Swift 3.0 und höher kompatibel zu machen

func getDateTimeDiff(dateStr:String) -> String {

    let formatter : DateFormatter = DateFormatter()
    formatter.timeZone = NSTimeZone.local
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"

    let now = formatter.string(from: NSDate() as Date)
    let startDate = formatter.date(from: dateStr)
    let endDate = formatter.date(from: now)

    // *** create calendar object ***
    var calendar = NSCalendar.current

    // *** Get components using current Local & Timezone ***
    print(calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: startDate!))

    // *** define calendar components to use as well Timezone to UTC ***
    let unitFlags = Set<Calendar.Component>([.year, .month, .day, .hour, .minute, .second])
    calendar.timeZone = TimeZone(identifier: "UTC")!
    let dateComponents = calendar.dateComponents(unitFlags, from: startDate!, to: endDate!)

    // *** Get Individual components from date ***
    let years = dateComponents.year!
    let months = dateComponents.month!
    let days = dateComponents.day!
    let hours = dateComponents.hour!
    let minutes = dateComponents.minute!
    let seconds = dateComponents.second!

    var timeAgo = ""

    if (seconds > 0){
        if seconds < 2 {
            timeAgo = "Second Ago"
        }
        else{
            timeAgo = "\(seconds) Second Ago"
        }
    }

    if (minutes > 0){
        if minutes < 2 {
            timeAgo = "Minute Ago"
        }
        else{
            timeAgo = "\(minutes) Minutes Ago"
        }
    }

    if(hours > 0){
        if minutes < 2 {
            timeAgo = "Hour Ago"
        }
        else{
            timeAgo = "\(hours) Hours Ago"
        }
    }

    if (days > 0) {
        if minutes < 2 {
            timeAgo = "Day Ago"
        }
        else{
            timeAgo = "\(days) Days Ago"
        }
    }

    if(months > 0){
        if minutes < 2 {
            timeAgo = "Month Ago"
        }
        else{
            timeAgo = "\(months) Months Ago"
        }
    }

    if(years > 0){
        if minutes < 2 {
            timeAgo = "Year Ago"
        }
        else{
            timeAgo = "\(years) Years Ago"
        }
    }

    DLog("timeAgo is ===> \(timeAgo)")
    return timeAgo;
}

0

Verwenden Sie diesen Code:

let registrationDateString = "2008-10-06 00:00:00"
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
    if let registrationDate = dateFormatter.date(from: registrationDateString) {
        let currentDate = Date()
        let dateDifference = Calendar.current.dateComponents([.day, .month, .year],
                                                               from: registrationDate,
                                                               to: currentDate)
        print("--------------------- Result: \(dateDifference.year ?? 0) years \(dateDifference.month ?? 0) months and \(dateDifference.day ?? 0) days")
    } else {
        print("--------------------- No result")
    }

Ausgabe ist: Ergebnis: 10 Jahre 1 Monate und 18 Tage


0
import Foundation

extension DateComponents {

    func dateComponentsToTimeString() -> String {

        var hour = "\(self.hour!)"
        var minute = "\(self.minute!)"
        var second = "\(self.second!)"

        if self.hour! < 10 { hour = "0" + hour }
        if self.minute! < 10 { minute = "0" + minute }
        if self.second! < 10 { second = "0" + second }

        let str = "\(hour):\(minute):\(second)"
        return str
    }

}

extension Date {

    func offset(from date: Date)-> DateComponents {
        let components = Set<Calendar.Component>([.second, .minute, .hour, .day, .month, .year])
        let differenceOfDate = Calendar.current.dateComponents(components, from: date, to: self)
        return differenceOfDate
    }
}

Verwenden:

var durationString: String {
        return self.endTime.offset(from: self.startTime).dateComponentsToTimeString()
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.