Получение разницы между двумя NSDates в (месяцы / дни / часы / минуты / секунды)
Я пытаюсь получить разницу между текущей датой как NSDate()
и дата из PHP time();
позвоните например: NSDate(timeIntervalSinceReferenceDate: 1417147270)
, Как мне узнать разницу во времени между двумя датами? Я хотел бы иметь функцию, которая сравнивает две даты и if(seconds > 60)
тогда это возвращает минуты, if(minutes > 60)
вернуть часы и if(hours > 24)
вернуть дни и тд.
Как я должен идти об этом?
РЕДАКТИРОВАТЬ: текущий принятый ответ сделал именно то, что я хотел сделать. Я рекомендую его для простоты использования для получения времени между двумя датами в форме, что этот PHP time()
Функция использует. Если вы не особенно знакомы с PHP, это время в секундах с 1 января 1970 года. Это полезно для бэкэнда в PHP. Если, возможно, вы используете бэкэнд, такой как NodeJS, вы можете рассмотреть некоторые другие варианты, которые вы найдете ниже.
20 ответов
Xcode 9.3 • Swift 4.1
Вы можете использовать Календарь, чтобы помочь вам создать расширение для вычисления даты следующим образом:
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 amount of nanoseconds from another date
func nanoseconds(from date: Date) -> Int {
return Calendar.current.dateComponents([.nanosecond], from: date, to: self).nanosecond ?? 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" }
if nanoseconds(from: date) > 0 { return "\(nanoseconds(from: date))ns" }
return ""
}
}
Использование компонента форматирования даты
let dateComponentsFormatter = DateComponentsFormatter()
dateComponentsFormatter.allowedUnits = [.year,.month,.weekOfMonth,.day,.hour,.minute,.second]
// Cannot add in .nanosecond here (⬆︎) as Swift 4.1 does not consider nanoseconds a calendrical unit
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 nanoseconds = date2.nanoseconds(from: date1) // 23,590,800,000,000,000
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 час 59 минут 20 секунд. Эта функция будет отображать "1 ч 59 м 20 с".
Вот мой код:
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 ""
}
}
В 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 ""
}
}
Swift 5.1 • iOS 13
Вы можете использовать RelativeDateFormatter, который был представлен Apple в iOS 13.
let exampleDate = Date().addingTimeInterval(-15000)
let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .full
let relativeDate = formatter.localizedString(for: exampleDate, relativeTo: Date())
print(relativeDate) // 4 hours ago
См. Как показать относительную дату и время с помощью RelativeDateTimeFormatter.
Ты спрашиваешь:
Я хотел бы иметь функцию, которая сравнивает две даты и если (секунд> 60), то возвращает минуты, если (минут> 60) возвращает часы и если (часы> 24) возвращают дни и так далее.
Я предполагаю, что вы пытаетесь построить строковое представление прошедшего времени между двумя датами. Вместо того чтобы писать собственный код для этого, у Apple уже есть класс, предназначенный именно для этого. А именно, использовать DateComponentsFormatter
, задавать allowedUnits
к любым значениям, имеющим смысл для вашего приложения, установите unitsStyle
к тому, что вы хотите (например, .full
), а затем позвоните string(from:to:)
,
Например, в 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)
Это также локализует строку, соответствующую данному устройству.
Или в 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)
Если вы ищете фактические числовые значения, просто используйте dateComponents
, Например, в Swift 3:
let components = Calendar.current.dateComponents([.month, .day, .hour, .minute, .second], from: previousDate, to: now)
Или в Swift 2.3:
let components = NSCalendar.currentCalendar().components([.Month, .Day, .Hour, .Minute, .Second], fromDate: previousDate, toDate: now, options: [])
-> Используйте это, чтобы найти промежуток времени между двумя датами в Swift(с двумя строками).
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
}
}
Комбинированный Extension + DateComponentsFormatter из ответа @ 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"
Слегка измененный код для 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!
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;
}
Я добавил "длинную" версию в ответ Лео Дабуса на тот случай, если вы хотите иметь строку, которая говорит что-то вроде "2 недели назад" вместо просто "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 ""
}
}
С Swift 3, в соответствии с вашими потребностями, вы можете выбрать один из двух следующих способов решения вашей проблемы.
1. Показать разницу между двумя датами для пользователя
Вы можете использовать DateComponentsFormatter
создавать строки для интерфейса вашего приложения. DateComponentsFormatter
имеет maximumUnitCount
свойство со следующей декларацией:
var maximumUnitCount: Int { get set }
Используйте это свойство, чтобы ограничить количество единиц, отображаемых в результирующей строке. Например, если для этого свойства установлено значение 2, а не "1 ч. 10 м., 30 с.", Результирующая строка будет "1 ч. 10 м.". Используйте это свойство, если вы ограничены в пространстве или хотите округлить значения до ближайшей большой единицы.
Установив maximumUnitCount
ценность для 1
Вы гарантированно отобразите разницу только в одном DateComponentsFormatter
Единица измерения (годы, месяцы, дни, часы или минуты).
Код игровой площадки ниже показывает, как отобразить разницу между двумя датами:
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")
Обратите внимание, что DateComponentsFormatter
округляет результат. Следовательно, разница в 4 часа и 30 минут будет отображаться как 5 часов.
Если вам нужно повторить эту операцию, вы можете изменить код:
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. Получите разницу между двумя датами без форматирования
Если вам не нужно отображать с форматированием разницу между двумя датами для пользователя, вы можете использовать Calendar
, Calendar
есть метод dateComponents(_:from:to:)
который имеет следующую декларацию:
func dateComponents(_ components: Set<Calendar.Component>, from start: Date, to end: Date) -> DateComponents
Возвращает разницу между двумя датами.
Код игровой площадки ниже, который использует dateComponents(_:from:to:)
показывает, как получить разницу между двумя датами, возвращая разницу только в одном типе Calendar.Component
(годы, месяцы, дни, часы или минуты).
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
}
}
Если вам нужно повторить эту операцию, вы можете изменить код:
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
}
В 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
}
Если ваша цель - получить точное число дней между двумя датами, вы можете обойти эту проблему следующим образом:
// 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
Вот мой ответ на Swift 3 ответы выше. Это актуально по состоянию на ноябрь 2016 года, выпуск XCode был 8,2 бета (8C23). Использовал некоторые из предложений Sagar и Emin, описанных выше, и иногда приходилось разрешать автозаполнению Xcode, чтобы предложить синтаксис. Казалось, что синтаксис действительно изменился на эту бета-версию. buyDate
Я получил от 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)")
Некоторое дополнение в ответе jose920405, чтобы сделать его совместимым с Swift 3.0 и выше
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;
}
Небольшое дополнение к ответу Лео Дабуса, чтобы обеспечить множественные версии и быть более читабельным.
Свифт 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 ""
}
}
Свифт 5
func dateDiff(dateStr:String) -> String {
let f:DateFormatter = DateFormatter()
f.timeZone = NSTimeZone.local
f.dateFormat = "yyyy-M-dd'T'HH:mm:ss.SSSZZZ"
let now = f.string(from: NSDate() as Date)
let startDate = f.date(from: dateStr)
let endDate = f.date(from: now)
var _: NSCalendar = NSCalendar.current as NSCalendar
let dateComponents = Calendar.current.dateComponents([ .weekOfMonth, .day , .hour , .minute , .second], from: startDate!, to: endDate!)
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;
}
Для XCode версии 8.3.3 и 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)")
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
}
}
Использование:
var durationString: String {
return self.endTime.offset(from: self.startTime).dateComponentsToTimeString()
}
Используйте этот код:
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")
}
Вывод: Результат: 10 лет 1 месяц и 18 дней
Это более короткая версия: в основном я пытаюсь получить разницу между отметкой времени после Date()
сейчас.
// 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))
}