【问题标题】:Swift display time ago from Date (NSDate)从日期(NSDate)开始快速显示时间
【发布时间】:2017-10-20 13:23:58
【问题描述】:

在一个单元格中,我想显示来自 Parse 服务器中 NSDate 的时间。这是代码,但它不起作用。什么都没有改变,数据也没有被解析。

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

【问题讨论】:

标签: ios swift swift3 parse-server


【解决方案1】:

如果您只想要 Date 的 Time Ago 扩展,请转到答案底部?

我将向您展示一个示例,只是为了在几秒钟之前以及之后我将展示您的扩展更新。

注意:如果需要,您可以直接使用 Pase 中的日期:

if let pastDate = (object?["createdAt"] as? Date) {
    cell.TimeAgo.text = pastDate.timeAgoDisplay()
}

斯威夫特 5.1

如何使用 Swift 5.1 显示几秒钟前的示例:

自iOS13以来苹果引入了一个新类RelativeDateTimeFormatter

extension Date {
    func timeAgoDisplay() -> String {
        let formatter = RelativeDateTimeFormatter()
        formatter.unitsStyle = .full
        return formatter.localizedString(for: self, relativeTo: Date())
    }
}

该类将允许您根据您的语言获取时间前的字符串。它会根据您的时间间隔自动选择正确的时间单位,这是一个示例:

|--------------------------|------------------|
| Time interval in seconds |      Display     |
|--------------------------|------------------|
|             -6           |   6 seconds ago  |
|            -60           |   1 minute ago   |
|           -600           |  10 minutes ago  |
|          -6000           |    1 hour ago    |
|         -60000           |   16 hours ago   |
|--------------------------|------------------|

您会注意到它会自动为您处理复数形式。

Swift 3Swift 4

如何使用 Swift 3Swift 4 获取几秒钟前的示例:

首先:要获得前几秒,我们需要检查我们是否有一分钟或更少,要获得当前日期减去一分钟,您可以这样写:

let minuteAgo = calendar.date(byAdding: .minute, value: -1, to: Date())!

第二:现在比较两个日期! (对于您的延期,我们自行替换 yourDate)并获取这两个日期之间的差异。

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

【讨论】:

  • 我为什么不打开我的代码。我之前是强制解包的,我用 if let 修复了它
  • 这个答案具有误导性。您没有处理单/复数单位和本地化。你应该改用DateComponentsFormatter
  • @Desdenova 感谢您告诉我,我会更新答案
  • 我制作了一个更新感觉树来告诉我它是否适合你
  • 很好,工作起来很有魅力
【解决方案2】:

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

例如看这个blog post

【讨论】:

  • 如何手动更改语言环境?
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    以字符串形式传递时间,例如2019-02-25 10:20:21 在变量 dateFormat 中传递 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"
    
                }
            }
    

    【讨论】:

    • 这个答案具有误导性。您没有处理单/复数单位和本地化。你应该改用DateComponentsFormatter
    • @Desdenova 再次检查代码,我已经处理了单数/复数单位并且不需要本地化。如果有人问我会更新答案
    【解决方案5】:
        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)
    

    【讨论】:

      【解决方案6】:

      终于在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")
          }
      

      【讨论】:

        【解决方案7】:

        这有点棘手)

        基本上你需要

        • 检查间隔
        • 选择感兴趣的组件
        • 检查是否需要商以及它是否适用于当前语言

        iOS 提供了几种方法来做到这一点

        1. 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分钟”

        1. RelativeDateTimeFormatter

          +: 不适用于本地化和其他与字符串相关的内容

          -: iOS13+

          let formatter = RelativeDateTimeFormatter()
          formatter.unitsStyle = .full
          return formatter.localizedString(for: self, relativeTo: Date())
          
        2. 自定义方式

          +: 灵活

          -: 编码一切

        示例:

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

        【讨论】:

          【解决方案8】:

          如果您只有 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
              }
          

          【讨论】:

            猜你喜欢
            • 2019-08-27
            • 2017-01-20
            • 1970-01-01
            • 1970-01-01
            • 2014-09-03
            • 2014-09-04
            • 2012-08-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多