【问题标题】:Swift - check if a timestamp is yesterday, today, tomorrow, or X days agoSwift - 检查时间戳是昨天、今天、明天还是 X 天前
【发布时间】:2017-01-13 16:20:23
【问题描述】:

我正在尝试确定如何确定给定的时间戳是今天还是 +1 / -1 天。本质上,我想做这样的事情(伪代码)

IF days_from_today(timestamp) == -1 RETURN 'Yesterday'
ELSE IF days_from_today(timestamp) == 0 RETURN 'Today'
ELSE IF days_from_today(timestamp) == 1 RETURN 'Tomorrow'
ELSE IF days_from_today(timestamp) < 1 RETURN days_from_today(timestamp) + ' days ago'
ELSE RETURN 'In ' + days_from_today(timestamp) + ' ago'

但至关重要的是,它需要在 Swift 中,而我正在努力处理 NSDate / NSCalendar 对象。我开始像这样计算时差:

let calendar = NSCalendar.currentCalendar()
let date = NSDate(timeIntervalSince1970: Double(timestamp))
let timeDifference = calendar.components([.Second,.Minute,.Day,.Hour],
    fromDate: date, toDate: NSDate(), options: NSCalendarOptions())

但是,以这种方式进行比较并不容易,因为 .Day 根据一天中的时间和时间戳而有所不同。在 PHP 中,我只是使用 mktime 根据一天的开始(即mktime(0,0,0))创建一个新日期,但我不确定在 Swift 中最简单的方法。

有人知道如何解决这个问题吗?也许最好扩展 NSDate 或类似的东西?

【问题讨论】:

    标签: ios swift nsdate nscalendar


    【解决方案1】:

    Swift 4 更新:

    let calendar = Calendar.current
    let date = Date()
            
    calendar.isDateInYesterday(date)
    calendar.isDateInToday(date)
    calendar.isDateInTomorrow(date)
    

    【讨论】:

    • 获取当前日期 (Date()) 并检查它是昨天还是明天有什么意义?看起来您想更改复制代码中的任何内容...
    【解决方案2】:

    斯威夫特 3/4/5:

    Calendar.current.isDateInToday(yourDate)
    Calendar.current.isDateInYesterday(yourDate)
    Calendar.current.isDateInTomorrow(yourDate)
    

    另外:

    Calendar.current.isDateInWeekend(yourDate)
    

    请注意,对于某些国家/地区,周末可能与周六至周日不同,这取决于日历。

    您也可以使用autoupdatingCurrent 代替current 日历,这将跟踪用户更新。你用同样的方法:

    Calendar.autoupdatingCurrent.isDateInToday(yourDate)
    

    CalendarNSCalendar 的类型别名。

    【讨论】:

    • 天哪,是的!正是我需要的。
    【解决方案3】:

    Calendar 具有所有三种情况的方法

    func isDateInYesterday(_ date: Date) -> Bool
    func isDateInToday(_ date: Date) -> Bool
    func isDateInTomorrow(_ date: Date) -> Bool
    

    要计算比昨天早的天数,请使用

    func dateComponents(_ components: Set<Calendar.Component>, 
                          from start: Date, 
                              to end: Date) -> DateComponents
    

    [.day] 传递给components 并从结果中获取day 属性。


    这是一个函数,它还通过剥离时间部分(Swift 3+)来考虑 is in 的早晚日期。

    func dayDifference(from interval : TimeInterval) -> String
    {
        let calendar = Calendar.current
        let date = Date(timeIntervalSince1970: interval)
        if calendar.isDateInYesterday(date) { return "Yesterday" }
        else if calendar.isDateInToday(date) { return "Today" }
        else if calendar.isDateInTomorrow(date) { return "Tomorrow" }
        else {
            let startOfNow = calendar.startOfDay(for: Date())
            let startOfTimeStamp = calendar.startOfDay(for: date)
            let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
            let day = components.day!
            if day < 1 { return "\(-day) days ago" }
            else { return "In \(day) days" }
        }
    }
    

    或者,您可以在昨天今天明天使用DateFormatter免费获取本地化字符串

    func dayDifference(from interval : TimeInterval) -> String
    {
        let calendar = Calendar.current
        let date = Date(timeIntervalSince1970: interval)
        let startOfNow = calendar.startOfDay(for: Date())
        let startOfTimeStamp = calendar.startOfDay(for: date)
        let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
        let day = components.day!
        if abs(day) < 2 {
            let formatter = DateFormatter()
            formatter.dateStyle = .short
            formatter.timeStyle = .none
            formatter.doesRelativeDateFormatting = true
            return formatter.string(from: date)
        } else if day > 1 {
            return "In \(day) days"
        } else {
            return "\(-day) days ago"
        }
    }
    

    更新:

    在 macOS 10.15 / iOS 13 中,RelativeDateTimeFormatter 被引入以返回相对于特定日期的(本地化)字符串。

    【讨论】:

    • 谢谢!顶部看起来很完美。对于底部,这里可能是上午 10 点,但时间戳可能是明天上午 9 点,这将与明天上午 11 点给出不同的结果。还是我误解了它的工作原理?
    • 好东西,再次感谢。我所做的唯一更改是几天前的行,通过添加abs 来删除否定,即return "\(abs(day)) days ago"
    • 你能帮我解决这个问题吗:-stackoverflow.com/questions/48320572/…@vadian
    • 您的“最佳”答案需要手动计算并检查每种情况,而默认情况下 iOS 可以完成一些工作
    • @VyachaslavGerchicov 哪个工作?请详细说明。
    【解决方案4】:

    Swift 5iOS 13 上使用 RelativeDateTimeFormatter,

    let formatter = RelativeDateTimeFormatter()
    formatter.dateTimeStyle = .named 
    
    formatter.localizedString(from: DateComponents(day: -1)) // "yesterday"
    formatter.localizedString(from: DateComponents(day: 1)) // "Tomorrow"
    formatter.localizedString(from: DateComponents(hour: 2)) // "in 2 hours"
    formatter.localizedString(from: DateComponents(minute: 45)) // "in 45 minutes"
    

    【讨论】:

      【解决方案5】:

      1)根据您的示例,您希望收到“昨天”、“今天”等标签。iOS 默认可以这样做:

      https://developer.apple.com/documentation/foundation/nsdateformatter/1415848-doesrelativedateformatting?language=objc

      2)如果您想在 iOS 不自行添加这些标签时计算自定义标签,那么您也可以使用 2 个 DateFormatter 对象与 doesRelativeDateFormatting == truedoesRelativeDateFormatting == false 并比较它们的结果日期字符串是否为相同或不同

      【讨论】:

        【解决方案6】:

        NSCalender 有可以直接使用的新方法。

        NSCalendar.currentCalendar().isDateInTomorrow(NSDate())//Replace NSDate() with your date
        NSCalendar.currentCalendar().isDateInYesterday()
        NSCalendar.currentCalendar().isDateInTomorrow()
        

        希望对你有帮助

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-26
          • 2012-03-12
          • 1970-01-01
          • 2011-05-02
          • 2023-01-30
          • 2016-05-28
          • 2021-11-28
          • 2014-12-22
          相关资源
          最近更新 更多