2016-03-19 3 views
0

Je veux faire des calculs de temps et je ne peux pas savoir quelle classe utiliser, dois-je utiliser NSDate?Dois-je utiliser NSDate pour suivre l'heure d'arrivée et le retard?

Je veux que l'utilisateur entre l'heure qu'il devrait être au travail tous les jours et l'application lui montrera son temps moyen en retard/tôt en minutes.

explication Mieux: Lorsque l'utilisateur lance l'application pour la première fois, l'application lui demande quand il doit être au travail et quand il doit partir. L'application suit quand l'utilisateur arrive/quitte (en utilisant l'adresse de travail et le géofencing) et calcule la moyenne tardive et moyenne de l'utilisateur au travail. Lorsque l'utilisateur ouvre l'application, il voit deux étiquettes, l'une pour «moyenne tard» et l'autre pour «moyenne précoce».

Dois-je utiliser NSDate pour cela ou y at-il un meilleur moyen?

+0

La meilleure référence de tutoriel pour votre question est - http://rypress.com/tutorials/objective-c/data-types/dates – user3182143

+1

J'irais avec NSDateComponents, car il n'est pas vraiment connecté au seul point dans le temps une instance NSDate représente. – vikingosegundo

Répondre

1

Si vous comparez simplement des durées, NSTimeInterval est le type pour vous (c'est vraiment un float nombre de millisecondes qui explique son intention au lecteur).

NSDate est nécessaire pour les calculs qui doivent commencer ou se terminer avec l'heure réelle.

EDIT Avec le problème plus spécifique décrit: étant donné le début de travail quotidien d'un utilisateur, calculer l'écart de ce moment où l'arrivée au travail, le calcul clé implique NSDate.

Il vise à répondre à la question: l'utilisateur est-il à l'heure ou non, en ce moment, par rapport à l'horloge réelle? Les principaux params à ce calcul est l'heure actuelle NSDate et l'arrivée prévue de l'utilisateur du temps NSDate qui peut être enregistré en tant que simple et scalaires converti en NSDate via NSDateComponents ...

// core location triggered an arrival notification and we call this 
// assumes a "User" class that knows user state, like the time user is due at work 
-(void)userJustArrived:(User *)myUser { 
    NSDate *now = [NSDate date]; 
    NSDate *dueAtWork = [myUser dueAtWork]; 
    NSTimeInterval lateness = [now timeIntervalSinceDate:dueAtWork]; 

    // a negative lateness means user is early 
    if (lateness > 0) 
     NSLog(@"you are %f milliseconds late. perhaps you should go into standup comedy", lateness); 
} 

// on the user class, due at work produces an NSDate from what you would 
// have stored earlier as the time when a user is expected at work 
- (NSDate *)dueAtWork { 
    NSCalendar *calendar = [NSCalendar currentCalendar]; 
    NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]]; 
    // these are given as user state, the user's planned start time 
    components.hour = self.dueAtWorkHour; 
    components.minute = self.dueAtWorkMinute; 
    return [components date]; 
} 
+0

Je vais essayer de mieux m'expliquer. Lorsque l'utilisateur lance l'application pour la première fois, l'application lui demande quand il devrait être au travail et quand il devrait partir. L'application suit quand l'utilisateur arrive/quitte (en utilisant l'adresse de travail et le géofencing) et calcule la moyenne tardive et moyenne de l'utilisateur au travail. Lorsque l'utilisateur ouvre l'application, il voit deux étiquettes, l'une pour «moyenne tard» et l'autre pour «moyenne précoce». Donc, j'espère que vous comprenez :). Quelle est la meilleure façon de le faire? Je vous remercie! –

+0

Ce sont définitivement des questions NSDate car elles se rapportent à des temps réels sur une horloge ("quelle heure"). Je pense que ce problème appelle l'utilisation de NSDates (conversion d'entrée en NSDate, stockage d'un NSDate, conversion en flottants uniquement pour faire de l'arithmétique). – danh

+0

Alors, comment est-ce que je peux stocker l'heure seulement sur 'NSDate'/vérifier si l'utilisateur est arrivé à un certain temps sans référence à la date? –

1

En général, si vous voulez garder une trace de " Humain "(c'est-à-dire la date et les heures que vous trouverez sur un calendrier ou une horloge), l'outil que vous voulez est NSDateComponents, couplé avec NSCalendar. L'objectif de NSDate est de garder une trace des moments absolus dans le temps, (*) en termes de secondes depuis un moment de référence, ce qui n'est généralement pas la façon dont les gens pensent du temps. NSDate devient rapidement incorrecte et souvent contre-productive dès que vous traitez avec des fuseaux horaires, l'heure d'été, ou toute autre chose qui salit la belle cartographie des « secondes écoulées depuis l'époque » et « l'horloge sur le mur. » (*) Mettez de côté la relativité et ce qui ne l'est pas, et supposez que nous pouvons tous être d'accord quand les choses arrivent et que les intervalles de temps peuvent être combinés de façon commutative et transitive dans un univers newtonien simple et agréable. Ignorez également les problèmes comme les secondes intercalaires ou toute autre chose qui pourrait compliquer les choses, et vous avez NSDate.


Voici une implémentation réelle qui devrait gérer la plupart des bizarreries (comme les temps au-dessus de minuit). Peut ne pas gérer les transitions DST correctement, mais cela devrait vous mettre sur la bonne voie.

let twelveHours: NSTimeInterval = 12 * 60 * 60 

func timeLateBetweenDate(actualDate: NSDate, nominalHour: Int, nominalMinute: Int) -> NSTimeInterval { 

    func timeLateOnDate(onDate: NSDate) -> NSTimeInterval { 
     let calendar = NSCalendar.currentCalendar() 
     let expectedDate = calendar.dateBySettingHour(nominalHour, minute: nominalMinute, second: 0, ofDate: onDate, options: [])! 

     let todayDifference = actualDate.timeIntervalSinceDate(expectedDate) 

     if todayDifference > twelveHours { // Over 12 hours late; should have checked against tomorrow 
      return timeLateOnDate(calendar.dateByAddingUnit(.Day, value: 1, toDate: onDate, options: [])!) 
     } else if todayDifference < -twelveHours { // Over 12 hours early, should have checked against yesterday 
      return timeLateOnDate(calendar.dateByAddingUnit(.Day, value: -1, toDate: onDate, options: [])!) 
     } 
     else { 
      return todayDifference 
     } 
    } 

    return timeLateOnDate(actualDate) 
} 

Et dans un peu bâclée ObjC (juste translittération Swift, ce qui serait probablement plus claire comme méthode):

NSTimeInterval twelveHours = 12 * 60 * 60; 

NSTimeInterval _timeLateOnDate(NSDate *onDate, NSDate *actualDate, NSUInteger nominalHour, NSUInteger nominalMinute) { 
    NSCalendar *calendar = [NSCalendar currentCalendar]; 
    NSDate *expectedDate = [calendar dateBySettingHour:nominalHour minute: nominalMinute second: 0 ofDate: onDate options: 0]; 

    NSTimeInterval todayDifference = [actualDate timeIntervalSinceDate:expectedDate]; 

    if (todayDifference > twelveHours) { // Over 12 hours late; should have checked against tomorrow 
     return _timeLateOnDate([calendar dateByAddingUnit:NSCalendarUnitDay value: 1 toDate: onDate options: 0], 
           actualDate, nominalHour, nominalMinute); 
    } else if (todayDifference < -twelveHours) { // Over 12 hours early, should have checked against yesterday 
     return _timeLateOnDate([calendar dateByAddingUnit:NSCalendarUnitDay value: -1 toDate: onDate options: 0], 
           actualDate, nominalHour, nominalMinute); 
    } else { 
     return todayDifference; 
    } 
} 


NSTimeInterval timeLateBetweenDateAndNominalHourMinute(NSDate *actualDate, NSUInteger nominalHour, NSUInteger nominalMinute) { 
    return _timeLateOnDate(actualDate, actualDate, nominalHour, nominalMinute); 
} 
+0

Alors, comment est-ce que je peux stocker l'heure seulement sur 'NSDateComponents'/vérifier si l'utilisateur est arrivé à un certain temps sans référence à la date? –

+0

Stockez juste l'heure et les minutes si c'est tout ce que vous voulez. Vous pouvez également stocker le jour, le mois et l'année nominaux si cela est utile. Vous pouvez stocker autant de composants que vous le souhaitez. –

+0

Afin de faire des maths sur un 'NSDateComponents', vous devrez généralement lui donner la date que vous voulez prendre en compte pour ces composants. C'est important s'il y a un changement de temps DST pendant la période.Si vous êtes prêt à ignorer les décalages temporels DST (aucun de vos temps ne sera jamais du jour au lendemain, par exemple), alors vous pouvez simplement faire des calculs simples sur les heures et les minutes. –

-1

Vous pouvez utiliser NSDateFormatter pour obtenir le régler l'heure de bureau réel pour chaque jour . Utilisez la méthode timeIntervalSinceDate: sur NSTimeInterval pour calculer la moyenne/fin en secondes.

+0

Mais comment puis-je ignorer la date? Je veux juste comparer l'heure –

0

L'heure du jour que vous souhaitez enregistrer n'est pas une date. Quelque chose comme "Februrary 9th 2016 10: 20: 30.7 UTC" est une date. "8h30 du matin" n'est pas une date que NSDate peut représenter.

Lorsque l'utilisateur entre l'heure, stockez l'heure et les minutes sous forme de deux nombres. Lorsque l'utilisateur arrive au travail, prenez la date actuelle, convertissez-la en composants de date avec votre calendrier local pour obtenir la date du jour, créez un NSDate avec la date du jour et les heures et minutes que l'utilisateur a saisies. comparer les deux NSDates. De cette façon, vous gérez l'heure d'été, etc. automatiquement. Vous gérez même la situation où l'utilisateur a entré la date pendant les vacances dans un fuseau horaire à six heures de la vôtre.

Veuillez ne pas demander de code. L'écriture de code est votre travail. Votre travail seul.