Swift iOS doesRelativeDateFormatting除了“今天”和“昨天”之外还有不同的价值?

时间:2014-12-05 07:25:29

标签: ios date swift nsdateformatter relative-date

我想要使用相对日期来表示一些日期,例如"今天,昨天,1周前,1个月前"等...

这是我正在使用的Swift代码:

let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .MediumStyle
dateFormatter.doesRelativeDateFormatting = true
let uploadDate = dateFormatter.stringFromDate(date)

只有"今天"和"昨天"代表,其余日期如下所示: 2014年11月24日 2014年11月17日 等...

是否有其他方式使用相对约会而不是实际日期来表示所有日期?

4 个答案:

答案 0 :(得分:24)

编辑/更新: Xcode 8.3.2•Swift 3.1

如果您使用扩展和日历方法来帮助您进行日历计算,这真的很容易:

extension Date {
    var yearsFromNow:   Int { return Calendar.current.dateComponents([.year],       from: self, to: Date()).year        ?? 0 }
    var monthsFromNow:  Int { return Calendar.current.dateComponents([.month],      from: self, to: Date()).month       ?? 0 }
    var weeksFromNow:   Int { return Calendar.current.dateComponents([.weekOfYear], from: self, to: Date()).weekOfYear  ?? 0 }
    var daysFromNow:    Int { return Calendar.current.dateComponents([.day],        from: self, to: Date()).day         ?? 0 }
    var hoursFromNow:   Int { return Calendar.current.dateComponents([.hour],       from: self, to: Date()).hour        ?? 0 }
    var minutesFromNow: Int { return Calendar.current.dateComponents([.minute],     from: self, to: Date()).minute      ?? 0 }
    var secondsFromNow: Int { return Calendar.current.dateComponents([.second],     from: self, to: Date()).second      ?? 0 }
    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 daysFromNow    > 0 { return daysFromNow == 1 ? "Yesterday" : "\(daysFromNow) days 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 ""
    }
}

<强>测试

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: 2017, month:  5, day: 18, hour: 22, minute: 39).date!
let date3 = DateComponents(calendar: calendar, year: 2017, month: 6, day:  2, hour: 12, minute: 38).date!
let date4 = DateComponents(calendar: calendar, year: 2017, month: 6, day:  3, hour: 14, minute: 45).date!
let date5 = DateComponents(calendar: calendar, year: 2017, month: 6, day:  3, hour: 15, minute:  18).date!

let timeOffset1 = date1.relativeTime // "1 year ago"
let timeOffset2 = date2.relativeTime // "2 weeks ago"
let timeOffset3 = date3.relativeTime // "Yesterday"
let timeOffset4 = date4.relativeTime // "33 minutes ago"
let timeOffset5 = date5.relativeTime // "Just now"

答案 1 :(得分:3)

iOS 13+现在具有RelativeDateFormatter

例如: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"

formatter.localizedString(for: date, relativeTo: Date())

答案 2 :(得分:2)

你应该看一下关于NSDateComponentsFormatter的Mattt Thompsons博客文章

http://nshipster.com/nsdatecomponents/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

示例(由Mattt Thompson撰写)

答案 3 :(得分:0)

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

Leo Dabus执行relativeTime的另一种实现方式,既可以做到未来也可以做到过去,而且更简洁。 (Swift2.3)