111 votes

Swift - vérifier si un timestamp est hier, aujourd'hui, demain ou il y a X jours

Je cherche à savoir comment décider si un timestamp donné se produit aujourd'hui, ou +1 / -1 jours. Essentiellement, j'aimerais faire quelque chose comme ceci (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'

Mais surtout, il faut que ce soit en Swift et j'ai du mal avec les objets NSDate / NSCalendar. J'ai commencé par calculer le décalage horaire comme suit :

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, il n'est pas facile de comparer de cette manière, car les .Day est différent selon l'heure et l'horodatage. En PHP, j'utiliserais simplement mktime pour créer une nouvelle date, basée sur le début de la journée (i.e. mktime(0,0,0) ), mais je ne suis pas sûr de la manière la plus simple de le faire en Swift.

Quelqu'un a-t-il une bonne idée de la manière d'aborder cette question ? Peut-être qu'une extension de NSDate ou quelque chose de similaire serait la meilleure solution ?

225voto

KlimczakM Points 6093

Swift 3/4/5 :

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

En outre :

Calendar.current.isDateInWeekend(yourDate)

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

Vous pouvez également utiliser autoupdatingCurrent au lieu de current qui suivra 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 l'élément NSCalendar .

1 votes

Omg oui ! Juste ce dont j'avais besoin.

161voto

vadian Points 29149

Calendar dispose de 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 antérieurs à hier, utilisez

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

passer [.day] a components et obtenir le day du résultat.


Il s'agit d'une fonction qui prend également en compte is in pour les dates antérieures et postérieures en supprimant la partie temporelle (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" }
    }
}

Vous pouvez également utiliser DateFormatter para Hier , Aujourd'hui y Demain pour obtenir gratuitement des chaînes localisées

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

Mise à jour :

Dans macOS 10.15 / iOS 13 RelativeDateTimeFormatter a été introduite pour renvoyer des chaînes de caractères (localisées) relatives à une date spécifique.

0 votes

Merci de votre attention ! La partie supérieure est parfaite. Pour la partie inférieure, il pourrait être 10 heures du matin ici, mais l'horodatage pourrait être 9 heures demain, ce qui donnerait un résultat différent de celui obtenu s'il était 11 heures demain. Ou ai-je mal compris comment cela fonctionne ?

0 votes

Excellent travail, merci encore. La seule modification que j'ai apportée concerne la ligne "il y a quelques jours". abs pour supprimer la négation, c'est-à-dire return "\(abs(day)) days ago"

0 votes

Pourriez-vous m'aider à répondre à cette question ? stackoverflow.com/questions/48320572/ @vadian

30voto

Edward Points 725

Mise à jour de Swift 4 :

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

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

2 votes

Quel est l'intérêt de prendre la date du jour ( Date() ) et vérifier si c'est hier ou demain ? Il semble que vous vouliez changer quelque chose dans un code copié...

11voto

nishith Singh Points 1426

NSCalender dispose 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 vous aidera

2voto

1) Selon votre exemple, vous souhaitez recevoir les étiquettes "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 voulez calculer votre étiquette personnalisée lorsque iOS n'ajoute pas ces étiquettes lui-même, vous pouvez utiliser 2 DateFormatter avec à la fois des objets doesRelativeDateFormatting == true y doesRelativeDateFormatting == false et comparer si leurs chaînes de date de résultat sont identiques ou différentes

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X