Snel – controleer of een tijdstempel gisteren, vandaag, morgen of X dagen geleden is

Ik probeer erachter te komen hoe ik kan beslissen of een bepaalde tijdstempel vandaag of +1 / -1 dagen voorkomt. In wezen zou ik zoiets willen doen (pseudocode)

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'

Het is echter cruciaal dat het in Swift moet zijn en ik worstel met de NSDate / NSCalendar-objecten. Ik begon met het berekenen van het tijdsverschil als volgt:

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

Op deze manier vergelijken is echter niet eenvoudig, omdat de .Dayverschilt afhankelijk van het tijdstip en de tijdstempel. In PHP zou ik mktime gewoon gebruiken om een ​​nieuwe datum te maken, gebaseerd op het begin van de dag (dwz mktime(0,0,0)), maar ik weet niet zeker wat de gemakkelijkste manier is om dat in Swift te doen.

Heeft iemand een goed idee hoe dit aan te pakken? Misschien is een uitbreiding op NSDate of iets dergelijks het beste?


Antwoord 1, autoriteit 100%

Swift 3/4/5:

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

Aanvullend:

Calendar.current.isDateInWeekend(yourDate)

Houd er rekening mee dat voor sommige landen het weekend anders kan zijn dan zaterdag-zondag, dit hangt af van de kalender.

Je kunt ook autoupdatingCurrentgebruiken in plaats van de currentkalender, die gebruikersupdates bijhoudt. Je gebruikt het op dezelfde manier:

Calendar.autoupdatingCurrent.isDateInToday(yourDate)

Calendaris een type-alias voor de NSCalendar.


Antwoord 2, autoriteit 82%

Calendarheeft methoden voor alle drie de gevallen

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

Gebruik om de dagen eerder dan gisteren te berekenen

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

geef [.day]door aan componentsen haal de eigenschap dayuit het resultaat.


Dit is een functie die ook beschouwt is invoor eerdere en latere datums door het tijdgedeelte te verwijderen (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" }
    }
}

U kunt ook DateFormattergebruiken voor Gisteren, Vandaagen Morgenom gratis gelokaliseerde tekenreeksen te krijgen

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

Bijwerken:

In macOS 10.15 / iOS 13 werd RelativeDateTimeFormattergeïntroduceerd om (gelokaliseerde) tekenreeksen te retourneren ten opzichte van een specifieke datum.


Antwoord 3, autoriteit 11%

Swift 4-update:

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

Antwoord 4, autoriteit 5%

NSCalender heeft nieuwe methoden die u direct kunt gebruiken.

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

Hopelijk helpt dit


Antwoord 5, autoriteit 4%

Op Swift 5en iOS 13gebruik de 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"

Antwoord 6

1)Volgens uw voorbeeld wilt u de labels “Gisteren”, “Vandaag” enz. ontvangen. iOS kan dit standaard doen:

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

2)Als u uw aangepaste label wilt berekenen wanneer iOS deze labels niet zelf toevoegt, kunt u ook 2 DateFormatter-objecten gebruiken met beide doesRelativeDateFormatting == trueen doesRelativeDateFormatting == falseen vergelijk of hun resultaatdatumstrings hetzelfde of verschillend zijn

Other episodes