Swift-检查时间戳记是昨天,今天,明天还是X天之前


70

我正在尝试确定如何确定给定的时间戳发生在今天还是+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或类似的东西是最好的?

Answers:


129

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]给结果componentsday从结果中获取属性。


此功能还is in通过删除时间部分(Swift 3+)来考虑较早和较晚的日期。

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 13RelativeDateTimeFormatter中引入了相对于特定日期返回(本地化)字符串的功能。


谢谢!顶部看起来很完美。在底部,这里可能是上午10点,但是时间戳可能是明天上午9点,如果明天是上午11点,则结果会有所不同。还是我误会了它的工作原理?
2016年

好东西,再次感谢。我所做的唯一更改是前一天的行,通过添加abs来删除否定字,即return "\(abs(day)) days ago"
Ben

可以ü帮助我解决这个问题: - stackoverflow.com/questions/48320572/... @vadian
迪利普·蒂瓦里

您的“最佳”答案需要手动计算并检查每种情况,而默认情况下,iOS可以完成一些工作
Vyachaslav Gerchicov

@VyachaslavGerchicov哪个工作?请详细说明。
vadian

148

迅捷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)

Calendar是的类型别名NSCalendar


1
天哪!正是我所需要的。
Khoury

18

Swift 4更新:

    let calendar = Calendar.current
    let date = Date()

    calendar.isDateInYesterday(date)
    calendar.isDateInToday(date)
    calendar.isDateInTomorrow(date)

取当前日期(Date())并检查是昨天还是明天有什么意义?看来您想更改复制代码中的任何内容……
KlimczakM,

7

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

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

希望这可以帮助


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"

2

1)根据您的示例,您希望接收标签“ Yesterday”,“ Today”等。iOS可以默认执行以下操作:

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

2)如果要计算您的自定义标签时的iOS不要自行添加这些标签,那么你也可以用2个DateFormatter对象既doesRelativeDateFormatting == truedoesRelativeDateFormatting == false和比较,如果其结果的日期字符串是相同的或不同

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.