Быстрое время назад от объекта NSDate
В ячейке я хочу отобразить время назад с NSDate на сервере Parse. Вот код, но он не работает. Ничего не меняется, и данные не анализируются.
if let createdat = (object?["createdAt"] as? String){
let pastDate = Date(timeIntervalSinceNow: TimeInterval(createdat)!)
cell.TimeAgo.text = pastDate.timeAgoDisplay()
}
extension Date {
func timeAgoDisplay() -> String {
let secondsAgo = Int(Date().timeIntervalSince(self))
let minute = 60
let hour = 60 * minute
let day = 24 * hour
let week = 7 * day
if secondsAgo < minute {
return "\(secondsAgo) sec ago"
} else if secondsAgo < hour {
return "\(secondsAgo / minute) min ago"
} else if secondsAgo < day {
return "\(secondsAgo / hour) hrs ago"
} else if secondsAgo < week {
return "\(secondsAgo / day) days ago"
}
return "\(secondsAgo / week) weeks ago"
}
}
9 ответов
Если вы просто хотите продлить время до даты, перейдите к нижней части ответа
Я покажу вам пример, чтобы получить секунды назад, а после я покажу ваше расширение обновлено.
Примечание: вы можете напрямую использовать дату из Pase, если хотите:
if let pastDate = (object?["createdAt"] as? Date){
cell.TimeAgo.text = pastDate.timeAgoDisplay()
}
Пример того, как получить секунды назад с Swift 3:
Во-первых: чтобы узнать количество секунд назад, нам нужно проверить, есть ли у нас одна минута или меньше, чтобы получить текущую дату минус одну минуту, вы можете написать:
let minuteAgo = calendar.date(byAdding: .minute, value: -1, to: Date())!
Второе: теперь сравните 2 даты! (В случае вашего продления мы заменяем yourDate на self) и получаем разницу между этими двумя датами.
if (minuteAgo < yourDate) {
let diff = Calendar.current.dateComponents([.second], from: yourDate, to: Date()).second ?? 0
print("\(diff) sec ago")
}
Вот и все, теперь вы можете распечатать время назад!
Итак, ваше расширение выглядит так: (Это простое расширение, чтобы узнать время назад)
extension Date {
func timeAgoDisplay() -> String {
let calendar = Calendar.current
let minuteAgo = calendar.date(byAdding: .minute, value: -1, to: Date())!
let hourAgo = calendar.date(byAdding: .hour, value: -1, to: Date())!
let dayAgo = calendar.date(byAdding: .day, value: -1, to: Date())!
let weekAgo = calendar.date(byAdding: .day, value: -7, to: Date())!
if minuteAgo < self {
let diff = Calendar.current.dateComponents([.second], from: self, to: Date()).second ?? 0
return "\(diff) sec ago"
} else if hourAgo < self {
let diff = Calendar.current.dateComponents([.minute], from: self, to: Date()).minute ?? 0
return "\(diff) min ago"
} else if dayAgo < self {
let diff = Calendar.current.dateComponents([.hour], from: self, to: Date()).hour ?? 0
return "\(diff) hrs ago"
} else if weekAgo < self {
let diff = Calendar.current.dateComponents([.day], from: self, to: Date()).day ?? 0
return "\(diff) days ago"
}
let diff = Calendar.current.dateComponents([.weekOfYear], from: self, to: Date()).weekOfYear ?? 0
return "\(diff) weeks ago"
}
}
Чтобы использовать это, это очень просто:
var now = Date()
now.timeAgoDisplay()
Swift 5.1 (iOS 13)
Начиная с iOS 13 вы можете использовать Apple RelativeDateFormatter. Преимущество в том, что результирующая строка локализована.
let date = Date().addingTimeInterval(-15000)
let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .full
let string = formatter.localizedString(for: date, relativeTo: Date())
print(string) // 4 hours ago
См., Например, это сообщение в блоге.
Вот решение в Swift 5:
extension Date {
func timeAgo() -> String {
let secondsAgo = Int(Date().timeIntervalSince(self))
let minute = 60
let hour = 60 * minute
let day = 24 * hour
let week = 7 * day
let month = 4 * week
let quotient: Int
let unit: String
if secondsAgo < minute {
quotient = secondsAgo
unit = "second"
} else if secondsAgo < hour {
quotient = secondsAgo / minute
unit = "min"
} else if secondsAgo < day {
quotient = secondsAgo / hour
unit = "hour"
} else if secondsAgo < week {
quotient = secondsAgo / day
unit = "day"
} else if secondsAgo < month {
quotient = secondsAgo / week
unit = "week"
} else {
quotient = secondsAgo / month
unit = "month"
}
return "\(quotient) \(unit)\(quotient == 1 ? "" : "s") ago"
}
}
Это немного сложно)
В основном вам нужно
- интервал проверки
- выбрать интересующие компоненты
- проверьте, требуется ли частное и применимо ли оно для текущего языка
iOS предоставляет несколько способов сделать это
DateComponentsFormatter
+: нет работы с локализацией и прочим строковым делом
-: не очень гибкий
let formatter = DateComponentsFormatter() formatter.allowedUnits = [.hour, .minute, .second] formatter.unitsStyle = .brief formatter.zeroFormattingBehavior = .dropAll let result = formatter.string(from: Date().advanced(by: -300), to: Date()) result
Результат:
"5 мин"
RelativeDateTimeFormatter
+: нет работы с локализацией и прочим строковым делом
-: iOS13+
let formatter = RelativeDateTimeFormatter() formatter.unitsStyle = .full return formatter.localizedString(for: self, relativeTo: Date())
Пользовательский способ
+: гибкий
-: кодировать все
Образец:
import Foundation
public extension Date {
struct DetailedDateSuffix {
let year: String
let month: String
let week: String
let day: String
let hour: String
let min: String
let second: String
let quotient: String
let suffix: String
public init(year: String,
week: String,
month: String,
day: String,
hour: String,
min: String,
second: String,
quotient: String,
suffix: String = String.empty) {
self.year = year
self.month = month
self.week = week
self.day = day
self.hour = hour
self.min = min
self.second = second
self.quotient = quotient
self.suffix = suffix
}
}
func toDetailedReadableFormat(_ suffix: DetailedDateSuffix) -> String {
if #available(iOS 13.0, *) {
let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .full
return formatter.localizedString(for: self, relativeTo: Date())
} else {
let calendar = Calendar.current
let ageComponents = calendar.dateComponents(
[
.year,
.month,
.weekOfYear,
.day,
.hour,
.minute,
.second
],
from: self,
to: Date())
var description: String = String.empty
if let years = ageComponents.year,
let months = ageComponents.month,
let weeks = ageComponents.weekOfYear,
let days = ageComponents.day,
let hours = ageComponents.hour,
let min = ageComponents.minute,
let sec = ageComponents.second {
var requireQuotient = false
if years > 0 {
description = "\(years)" + suffix.year
requireQuotient = years == 1
} else if months > 0 {
description = "\(months)" + suffix.month
requireQuotient = months == 1
} else if weeks > 0 {
description = "\(weeks)" + suffix.week
requireQuotient = weeks == 1
} else if days > 0 {
description = "\(days)" + suffix.day
requireQuotient = days == 1
} else if hours > 0 {
description = "\(hours)" + suffix.hour
requireQuotient = hours == 1
} else if min > 0 {
description = "\(min)" + suffix.min
requireQuotient = min == 1
} else if sec > 0 {
description = "\(sec)" + suffix.second
requireQuotient = sec == 1
}
description = requireQuotient ? "\(description)\(suffix.quotient)" : description
description = "\(description)\(suffix.suffix)"
}
return description
}
}
}
Передать время в виде строки в формате, например, 2019-02-25 10:20:21 Передать формат даты в переменную dateFormat
let dateFormat = "yyyy-MM-dd HH:mm:ss"
func timeInterval(timeAgo:String) -> String
{
let df = DateFormatter()
df.dateFormat = dateFormat
let dateWithTime = df.date(from: timeAgo)
let interval = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: dateWithTime!, to: Date())
if let year = interval.year, year > 0 {
return year == 1 ? "\(year)" + " " + "year ago" : "\(year)" + " " + "years ago"
} else if let month = interval.month, month > 0 {
return month == 1 ? "\(month)" + " " + "month ago" : "\(month)" + " " + "months ago"
} else if let day = interval.day, day > 0 {
return day == 1 ? "\(day)" + " " + "day ago" : "\(day)" + " " + "days ago"
}else if let hour = interval.hour, hour > 0 {
return hour == 1 ? "\(hour)" + " " + "hour ago" : "\(hour)" + " " + "hours ago"
}else if let minute = interval.minute, minute > 0 {
return minute == 1 ? "\(minute)" + " " + "minute ago" : "\(minute)" + " " + "minutes ago"
}else if let second = interval.second, second > 0 {
return second == 1 ? "\(second)" + " " + "second ago" : "\(second)" + " " + "seconds ago"
} else {
return "a moment ago"
}
}
let now = Date()
let pastDate = Date(timeIntervalSinceNow: -60 * 60 * 24)
enum DisplayTime {
case short
case long
var seconds: String {
switch self {
case .short: return "s"
case .long: return "seconds"
}
}
var minutes: String {
switch self {
case .short: return "m"
case .long: return "minutes"
}
}
var hours: String {
switch self {
case .short: return "h"
case .long: return "hours"
}
}
var days: String {
switch self {
case .short: return "d"
case .long: return "days"
}
}
var weeks: String {
switch self {
case .short: return "w"
case .long: return "weeks"
}
}
}
extension Date {
func timeAgoDisplay(_ display: DisplayTime) -> String {
let secondsAgo = Int(Date().timeIntervalSince(self))
let minute = 60
let hour = 60 * minute
let day = 24 * hour
let week = 7 * day
switch secondsAgo {
case let seconds where seconds < minute : return "\(secondsAgo) \(display.seconds) ago"
case let seconds where seconds < hour: return "\(secondsAgo / minute) \(display.minutes) ago"
case let seconds where seconds < day: return "\(secondsAgo / hour) \(display.hours) ago"
case let seconds where seconds < week: return "\(secondsAgo / day) \(display.days) ago"
default: "\(secondsAgo / week) \(display.weeks) ago"
}
return "\(secondsAgo / week) \(display.weeks) ago"
}
}
pastDate.timeAgoDisplay(.short)
Наконец-то получил простое решение для меня в swift4.2
let start = //Enter Start Date here....
let end = Date()
let formatter = DateComponentsFormatter()
formatter.maximumUnitCount = 2
formatter.unitsStyle = .full
formatter.allowedUnits = [.year, .month, .day]
let timeDifference = form.string(from: start, to: end)
print(timeDifference)
if timeDifference == "0 days"{
print("Today")
}
else if timeDifference == "1 days"{
print("\(timeDifference!)day ago")
}
else{
print("\(timeDifference!)days ago")
}
Если у вас есть только временная метка 1970 года. Вы можете использовать эту функцию для возврата времени назад.
private func timestampToStringAgo(timestamp: Int64) -> String{
let actualTime = Int64(Date().timeIntervalSince1970*1000)
var lastSeenTime = actualTime - timestamp
lastSeenTime /= 1000 //seconds
var lastTimeString = ""
if lastSeenTime < 60 {
if lastSeenTime == 1 {
lastTimeString = String(lastSeenTime) + " second ago"
} else {
lastTimeString = String(lastSeenTime) + " seconds ago"
}
} else {
lastSeenTime /= 60
if lastSeenTime < 60 {
if lastSeenTime == 1 {
lastTimeString = String(lastSeenTime) + " minute ago"
} else {
lastTimeString = String(lastSeenTime) + " minutes ago"
}
} else {
lastSeenTime /= 60
if lastSeenTime < 24 {
if lastSeenTime == 1 {
lastTimeString = String(lastSeenTime) + " hour ago"
} else {
lastTimeString = String(lastSeenTime) + " hours ago"
}
} else {
lastSeenTime /= 24
if lastSeenTime == 1 {
lastTimeString = String(lastSeenTime) + " day ago"
} else {
lastTimeString = String(lastSeenTime) + " days ago"
}
}
}
}
return lastTimeString
}
Как отобразить время назад с даты
Вы можете использоватьtimeIntervalSince
чтобы получить разницу между двумя датами в секундах. Затем сравните secondAgo с секундами, минутами, часами, днями, неделями, месяцами и годами, чтобы определить правильный суффикс строки.
Вы можете использовать эту функцию, чтобы вернуть отформатированное время назад, просто передав ей дату и предпочтение длинного (3 дня назад) или короткого (3 дня назад).
См. мое полное руководство здесь: Как отобразить время назад с даты
Полный код:
func getTimeSince(date: Date, isShort: Bool = false) -> String {
var formattedString = String()
let now = Date()
let secondsAgo = Int(now.timeIntervalSince(date))
let twoSeconds = 2
let minute = 60
let twoMinutes = minute * 2
let hour = 60 * minute
let twoHours = hour * 2
let day = 24 * hour
let twoDays = day * 2
let week = 7 * day
let twoWeeks = week * 2
let month = 4 * week
let twoMonths = month * 2
let year = 12 * month
let twoYears = year * 2
let secondString = isShort ? "s ago" : " second ago"
let secondsString = isShort ? "s ago" : " seconds ago"
let minuteString = isShort ? "m ago" : " minute ago"
let minutesString = isShort ? "m ago" : " minutes ago"
let hourString = isShort ? "h ago" : " hour ago"
let hoursString = isShort ? "h ago" : " hours ago"
let dayString = isShort ? "d ago" : " day ago"
let daysString = isShort ? "d ago" : " days ago"
let weekString = isShort ? "w ago" : " week ago"
let weeksString = isShort ? "w ago" : " weeks ago"
let monthString = isShort ? "mo ago" : " month ago"
let monthsString = isShort ? "mo ago" : " months ago"
let yearString = isShort ? "y ago" : " year ago"
let yearsString = isShort ? "y ago" : " years ago"
if secondsAgo < twoSeconds {
formattedString = "\(secondsAgo)\(secondString)"
} else if secondsAgo < minute {
formattedString = "\(secondsAgo)\(secondsString)"
} else if secondsAgo < twoMinutes {
formattedString = "\(secondsAgo / minute)\(minuteString)"
} else if secondsAgo < hour {
formattedString = "\(secondsAgo / minute)\(minutesString)"
} else if secondsAgo < twoHours {
formattedString = "\(secondsAgo / hour)\(hourString)"
} else if secondsAgo < day {
formattedString = "\(secondsAgo / hour)\(hoursString)"
} else if secondsAgo < twoDays {
formattedString = "\(secondsAgo / day)\(dayString)"
} else if secondsAgo < week {
formattedString = "\(secondsAgo / day)\(daysString)"
} else if secondsAgo < twoWeeks {
formattedString = "\(secondsAgo / week)\(weekString)"
} else if secondsAgo < month {
formattedString = "\(secondsAgo / week)\(weeksString)"
} else if secondsAgo < twoMonths {
formattedString = "\(secondsAgo / month)\(monthString)"
} else if secondsAgo < year {
formattedString = "\(secondsAgo / month)\(monthsString)"
} else if secondsAgo < twoYears {
formattedString = "\(secondsAgo / year)\(yearString)"
} else {
formattedString = "\(secondsAgo / year)\(yearsString)"
}
return formattedString
}
Использование:
let formattedTimeAgo = self.getTimeSince(date: date, isShort: false)