Swift iOS doesRelativeDateFormatting have different values besides “Today” and “Yesterday”?

后端 未结 4 1826
长发绾君心
长发绾君心 2021-02-12 21:17

I have a number of dates that I am trying to represent using a relative date such as \"Today, Yesterday, 1 week ago, 1 month ago\" etc...

This is the Swift code I am usi

相关标签:
4条回答
  • 2021-02-12 21:26

    iOS 13+ now has RelativeDateFormatter

    For examples: https://nshipster.com/formatter/#relativedatetimeformatter

    let formatter = RelativeDateTimeFormatter()
    formatter.localizedString(from: DateComponents(day: 1, hour: 1)) // "in 1 day"
    formatter.localizedString(from: DateComponents(day: -1)) // "1 day ago"
    

    or

    formatter.localizedString(for: date, relativeTo: Date())
    
    0 讨论(0)
  • 2021-02-12 21:32

    edit/Update: Xcode 8.3.2 • Swift 3.1

    It is really easy if you use extensions and Calendar methods to help you with your calendrical calculations:

    extension Date {
        var yearsFromNow: Int {
            return Calendar.current.dateComponents([.year], from: self, to: Date()).year!
        }
        var monthsFromNow: Int {
            return Calendar.current.dateComponents([.month], from: self, to: Date()).month!
        }
        var weeksFromNow: Int {
            return Calendar.current.dateComponents([.weekOfYear], from: self, to: Date()).weekOfYear!
        }
        var daysFromNow: Int {
            return Calendar.current.dateComponents([.day], from: self, to: Date()).day!
        }
        var isInYesterday: Bool {
            return Calendar.current.isDateInYesterday(self)
        }
        var hoursFromNow: Int {
            return Calendar.current.dateComponents([.hour], from: self, to: Date()).hour!
        }
        var minutesFromNow: Int {
            return Calendar.current.dateComponents([.minute], from: self, to: Date()).minute!
        }
        var secondsFromNow: Int {
            return Calendar.current.dateComponents([.second], from: self, to: Date()).second!
        }
        var relativeTime: String {
            if yearsFromNow > 0 { return "\(yearsFromNow) year" + (yearsFromNow > 1 ? "s" : "") + " ago" }
            if monthsFromNow > 0 { return "\(monthsFromNow) month" + (monthsFromNow > 1 ? "s" : "") + " ago" }
            if weeksFromNow > 0 { return "\(weeksFromNow) week" + (weeksFromNow > 1 ? "s" : "") + " ago" }
            if isInYesterday { return "Yesterday" }
            if daysFromNow > 0 { return "\(daysFromNow) day" + (daysFromNow > 1 ? "s" : "") + " ago" }
            if hoursFromNow > 0 { return "\(hoursFromNow) hour" + (hoursFromNow > 1 ? "s" : "") + " ago" }
            if minutesFromNow > 0 { return "\(minutesFromNow) minute" + (minutesFromNow > 1 ? "s" : "") + " ago" }
            if secondsFromNow > 0 { return secondsFromNow < 15 ? "Just now"
                : "\(secondsFromNow) second" + (secondsFromNow > 1 ? "s" : "") + " ago" }
            return ""
        }
    }
    

    Testing

    let calendar =  Calendar.current
    
    let date1 = DateComponents(calendar: calendar, year: 2016, month:  3, day: 14, hour: 22, minute: 39).date!
    let date2 = DateComponents(calendar: calendar, year: 2019, month:  4, day: 18, hour: 22, minute: 39).date!
    let date3 = DateComponents(calendar: calendar, year: 2019, month: 6, day:  2, hour: 12, minute: 38).date!
    let date4 = DateComponents(calendar: calendar, year: 2019, month: 6, day:  14, hour: 3, minute: 0).date!
    let date5 = DateComponents(calendar: calendar, year: 2019, month: 6, day:  17, hour: 23, minute: 45).date!
    let date6 = DateComponents(calendar: calendar, year: 2019, month: 6, day:  18, hour: 19, minute:  17).date!
    let timeOffset1 = date1.relativeTime // "3 years ago"
    let timeOffset2 = date2.relativeTime // "1 month ago"
    let timeOffset3 = date3.relativeTime // "2 weeks ago"
    let timeOffset4 = date4.relativeTime // "4 days ago"
    let timeOffset5 = date5.relativeTime // "Yesterday"
    let timeOffset6 = date6.relativeTime // "Just now"
    
    0 讨论(0)
  • 2021-02-12 21:34

    You should have a look at Mattt Thompsons Blog post about NSDateComponentsFormatter

    http://nshipster.com/nsdatecomponents/ and http://nshipster.com/nsformatter/

    let formatter = NSDateComponentsFormatter()
    formatter.unitsStyle = .Full
    
    let components = NSDateComponents()
    components.day = 1
    components.hour = 2
    
    let string = formatter.stringFromDateComponents(components)
    // 1 day, 2 hours
    

    Example (by Mattt Thompson)

    0 讨论(0)
  • 2021-02-12 21:52
    var relativeTime: String {
        // don't forget spacing on these constants.
        let futurePrefix = "" // " in" is a viable choice here...
        let pastSuffix = " ago" // " ago" is a viable choice here...
        let now = NSDate()
        for (method, unitName) in [
            (now.years, "year"),
            (now.months, "month"),
            (now.weeks, "week"),
            (now.days, "day"),
            (now.hours, "hour"),
            (now.minutes, "minute"),
            (now.seconds, "second")
        ] {
            let qty = method(self)
            let absQty = abs(method(self))
            if absQty > 0 {
                return (qty < 0 ? futurePrefix : "") +
                    String(absQty) + " " +
                    unitName +
                    (absQty == 1 ? "": "s") +
                    (qty > 0 ? pastSuffix : "")
            }
        }
        return ""
    }
    

    An alternative implementation of Leo Dabus's implementation of relativeTime that does both future and past and is more succinct. (Swift2.3)

    0 讨论(0)
提交回复
热议问题