the programming lenguaje language ios swift macos swift2 nsdate

ios - programming - Obteniendo la diferencia entre dos NSDates en(meses/días/horas/minutos/segundos)



the swift programming language pdf (18)

Estoy tratando de obtener la diferencia entre la fecha actual como NSDate() y una fecha de una time(); PHP time(); llame por ejemplo: NSDate(timeIntervalSinceReferenceDate: 1417147270) . ¿Cómo hago para obtener la diferencia de tiempo entre las dos fechas? Me gustaría tener una función que compare las dos fechas y if(seconds > 60) devuelve minutos, if(minutes > 60) devuelve horas y if(hours > 24) devuelve días, etc.

¿Cómo debo hacer esto?

EDITAR: La respuesta aceptada actual ha hecho exactamente lo que quería hacer. Lo recomiendo para un uso fácil para obtener el tiempo entre dos fechas en la forma que usa la función time() PHP. Si no está particularmente familiarizado con PHP, ese es el tiempo en segundos desde el 1 de enero de 1970. Esto es beneficioso para un back-end en PHP. Si tal vez está utilizando un backend como NodeJS, es posible que desee considerar algunas de las otras opciones que encontrará a continuación.


-> Use esto para encontrar el intervalo de tiempo entre dos fechas en Swift (con dos cadenas).

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


Agregué una versión "larga" a la respuesta de Leo Dabus en caso de que desee tener una cadena que diga algo así como "hace 2 semanas" en lugar de solo "2w" ...

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


Alguna adición en jose920405 responde para que sea compatible con Swift 3.0 y superior

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


Aquí está mi respuesta para las respuestas de Swift 3 anteriores. Esto es actual a partir de noviembre de 2016, la versión de Xcode fue 8.2 Beta (8C23). Usé algunas de las sugerencias de Sagar y Emin anteriores y, a veces, tuve que dejar que Xcode se completara automáticamente para sugerir la sintaxis. Parecía que la sintaxis realmente cambió a esta versión beta. buyDate que obtuve de un DatePicker:

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


Código ligeramente modificado para 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!


Con Swift 3, de acuerdo con sus necesidades, puede elegir una de las dos formas siguientes para resolver su problema.

1. Mostrar la diferencia entre dos fechas al usuario

Puede usar un DateComponentsFormatter para crear cadenas para la interfaz de su aplicación. DateComponentsFormatter tiene una propiedad maximumUnitCount con la siguiente declaración:

var maximumUnitCount: Int { get set }

Use esta propiedad para limitar el número de unidades que se muestran en la cadena resultante. Por ejemplo, con esta propiedad establecida en 2, en lugar de "1h 10m, 30s", la cadena resultante sería "1h 10m". Use esta propiedad cuando tenga limitaciones de espacio o desee redondear los valores a la unidad grande más cercana.

Al establecer el valor de maximumUnitCount en 1 , se garantiza que mostrará la diferencia en una DateComponentsFormatter unidad de DateComponentsFormatter (años, meses, días, horas o minutos).

El siguiente código de Playground muestra cómo mostrar la diferencia entre dos fechas:

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

Tenga en cuenta que DateComponentsFormatter redondea el resultado. Por lo tanto, una diferencia de 4 horas y 30 minutos se mostrará como 5 horas .

Si necesita repetir esta operación, puede refactorizar su código:

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. Obtenga la diferencia entre dos fechas sin formatear

Si no necesita mostrar al usuario el formato de la diferencia entre dos fechas, puede usar el Calendar . Calendar tiene un método dateComponents(_:from:to:) que tiene la siguiente declaración:

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

Devuelve la diferencia entre dos fechas.

El siguiente código de Playground que usa dateComponents(_:from:to:) muestra cómo recuperar la diferencia entre dos fechas devolviendo la diferencia en un solo tipo de Calendar.Component (años, meses, días, horas o minutos).

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

Si necesita repetir esta operación, puede refactorizar su código:

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 }


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


Esta es la versión más corta: Básicamente trato de obtener la diferencia entre la marca de tiempo de la Date() con la Date() ahora.

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


Extension + DateComponentsFormatter combinados de la respuesta de @ leo-dabus

Xcode 8.3 • Swift 3.1

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


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

Aquí está mi código:

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


Si su propósito es obtener el número de día exacto entre dos fechas, puede solucionar este problema de la siguiente manera:

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


Una pequeña adición a la respuesta de Leo Dabus para proporcionar las versiones en plural y ser más legible para los humanos.

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


Usa este código:

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

La producción es: Resultado: 10 años 1 mes y 18 días


Usted pregunta:

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

Supongo que está tratando de construir una representación de cadena del tiempo transcurrido entre dos fechas. En lugar de escribir su propio código para hacerlo, Apple ya tiene una clase diseñada para hacer precisamente eso. Es decir, use DateComponentsFormatter , establezca allowedUnits a los valores que tengan sentido para su aplicación, configure unitsStyle a lo que desee (por ejemplo, .full ) y luego llame a 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: [])


Para XCode versión 8.3.3 y 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)")


Xcode 8.3 • Swift 3.1 o posterior

Puede usar el 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 = [.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"


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"


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

Utilizar:

var durationString: String { return self.endTime.offset(from: self.startTime).dateComponentsToTimeString() }