web-dev-qa-db-fra.com

Swift - vérifie si l'horodatage est hier, aujourd'hui, demain ou il y a X jours

J'essaie de trouver un moyen de décider si un horodatage donné a lieu aujourd'hui ou si un jour ou un jour est écoulé. Essentiellement, j'aimerais faire quelque chose comme ça (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'

Surtout, il doit être dans Swift et je me bats avec les objets NSDate/NSCalendar. J'ai commencé par calculer le décalage horaire comme ceci:

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

Cependant, comparer de cette façon n’est pas facile, car le .Day est différent selon l’heure et l’horodatage. Dans PHP, j'utilisais simplement mktime pour créer une nouvelle date, en fonction du début de la journée (c'est-à-dire mktime(0,0,0)), mais je ne suis pas sûr du moyen le plus simple de le faire dans Swift.

Est-ce que quelqu'un a une bonne idée sur la façon d'aborder cela? Peut-être une extension à NSDate ou quelque chose de similaire serait la meilleure?

33
Ben

Calendar a des méthodes pour les trois cas

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

Pour calculer les jours plus tôt qu'hier, utilisez

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

passez [.day] à components et obtenez la propriété day à partir du résultat.


Cette fonction prend également en compte is in pour les dates antérieures et ultérieures en supprimant la partie heure (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" }
    }
}

Sinon, vous pouvez utiliser DateFormatter pour Hier , Aujourd'hui et Demain pour obtenir des chaînes localisées gratuitement

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

Swift 3/4:

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

Aditionellement:

Calendar.current.isDateInWeekend(yourDate)

Notez que pour certains pays, le week-end peut être différent du samedi au dimanche, cela dépend du calendrier.

Vous pouvez également utiliser autoupdatingCurrent au lieu de current calendar, qui permettra de suivre les mises à jour des utilisateurs. Vous l'utilisez de la même manière:

Calendar.autoupdatingCurrent.isDateInToday(yourDate)

Calendar est un alias de type pour NSCalendar.

70
KlimczakM

Mise à jour de Swift 4:

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

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

NSCalendar a de nouvelles méthodes que vous pouvez utiliser directement.

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

J'espère que cela t'aides

6
nishith Singh

1) Selon votre exemple, vous souhaitez recevoir les libellés "Hier", "Aujourd'hui", etc. iOS peut le faire par défaut:

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

2) Si vous souhaitez calculer votre étiquette personnalisée lorsque iOS n'ajoute pas ces étiquettes seule, vous pouvez également utiliser 2 objets DateFormatter avec doesRelativeDateFormatting == true et doesRelativeDateFormatting == false et comparer si leurs chaînes de date de résultat sont identiques ou différentes.

0