Saltar al contenido

Obtener la diferencia entre dos fechas (meses / días / horas / minutos / segundos) en Swift

Solución:

Xcode 8.3 • Swift 3.1 o posterior

Puede usar Calendario para ayudarlo a crear una extensión para hacer sus cálculos de fecha de la siguiente manera:

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

Uso del formateador de componentes de fecha

let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.allowedUnits = [.second, .minute, .hour, .day, .weekOfMonth, .month, .year]
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"

Si alguien necesita mostrar todas las unidades de tiempo, por ejemplo, “horas, minutos, segundos”, no solo “horas”. Digamos que la diferencia de tiempo entre dos fechas es 1 hora 59 minutos 20 segundos. Esta función mostrará “1h 59m 20s”.

Aquí está mi código Objective-C:

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

}

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

}

Usted pregunta:

Me gustaría tener una función que compare las dos fechas y si (segundos> 60) luego devuelve minutos, si (minutos> 60) devuelve horas y si (horas> 24) devuelve días y así sucesivamente.

Supongo que está intentando crear una representación de cadena del tiempo transcurrido entre dos fechas. En lugar de escribir su propio código para hacer eso, Apple ya tiene una clase diseñada para hacer precisamente eso. Es decir, utilice DateComponentsFormatter, colocar allowedUnits a los valores que tengan sentido para su aplicación, establezca unitsStyle a lo que quieras (p. ej. .full), y luego llame string(from:to:).

Por ejemplo, en 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)

Esto también localizará la cadena apropiada para el dispositivo en cuestión.

O, en 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)

Si está buscando los valores numéricos reales, simplemente use dateComponents. Por ejemplo, en Swift 3:

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

O, en Swift 2.3:

let components = NSCalendar.currentCalendar().components([.Month, .Day, .Hour, .Minute, .Second], fromDate: previousDate, toDate: now, options: [])
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *