[résolu] Problème NSDate increment

NasatyaNasatya Membre
octobre 2011 modifié dans Apple Developer Programs #1
Bonjour je me heurte a un problème qui parait simple mais dont je comprends pas la source je m'explique. J'ai une date que je dois incrémenter 28 fois du coup dans un for j'appelle une de mes fonctions qui incrémente la date de départ de un jour multiplié par le compteur de mon "for":

-(void)viewDidLoad{<br />&nbsp; &nbsp; [super viewDidLoad];<br />&nbsp; &nbsp; arrayMut = [[NSMutableArray alloc] init];<br />&nbsp; &nbsp; for (int i = 0 ; i&lt;28; i++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; NSString *dateinc = [self dateIncrementWithDate:@&quot;2011-10-10&quot; cpt:i];<br />&nbsp; &nbsp; &nbsp; &nbsp; [arrayMut addObject:dateinc];<br />&nbsp; &nbsp; }<br />}<br />-(NSString *)dateIncrementWithDate:(NSString *)dateStr cpt:(int)cpt{<br />&nbsp; &nbsp; NSDateFormatter *format = [[[NSDateFormatter alloc] init] autorelease];<br />&nbsp; &nbsp; [format setDateFormat:@&quot;yyyy-MM-dd&quot;];<br />&nbsp; &nbsp; NSDate *date = [format dateFromString:dateStr];<br />&nbsp; &nbsp; NSTimeInterval time = 24*3600*cpt;<br />&nbsp; &nbsp; NSDate *dateEnvoie = [[NSDate alloc] initWithTimeInterval:time sinceDate:date];<br />&nbsp; &nbsp; NSString *maDate = [format stringFromDate:dateEnvoie];<br />&nbsp; &nbsp; [dateEnvoie release];<br />&nbsp; &nbsp; return maDate;<br />}


Dans mon tableau la fonction m'affiche deux fois la date 2011-10-30 et une seul fois toutes les autres date. Alors que dans mes NSLog date est toujours identique.

Si jamais je modifie un peu mon code comme ça :

-(void)viewDidLoad{<br />&nbsp; &nbsp; [super viewDidLoad];<br />&nbsp; &nbsp; arrayMut = [[NSMutableArray alloc] init];<br />&nbsp; &nbsp; for (int i = 0 ; i&lt;28; i++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; NSString *dateinc = [self dateIncrementWithDate:i];<br />&nbsp; &nbsp; &nbsp; &nbsp; [arrayMut addObject:dateinc];<br />&nbsp; &nbsp; }<br />}<br />-(NSString *)dateIncrementWithDate:(int)cpt{<br />&nbsp; &nbsp; NSDateFormatter *format = [[[NSDateFormatter alloc] init] autorelease];<br />&nbsp; &nbsp; [format setDateFormat:@&quot;yyyy-MM-dd&quot;];<br />&nbsp; &nbsp; NSTimeInterval time = 24*3600*cpt;<br />&nbsp; &nbsp; NSDate *dateEnvoie = [[NSDate alloc] initWithTimeInterval:time sinceDate:[NSDate date]];<br />&nbsp; &nbsp; NSString *maDate = [format stringFromDate:dateEnvoie];<br />&nbsp; &nbsp; [dateEnvoie release];<br />&nbsp; &nbsp; return maDate;<br />}


La ça fonctionne bien j'ai toutes mes dates comme il faut. Je sais pas trop quoi faire pour régler le problème. Merci d'avance pour vos réponses

Réponses

  • devulderdevulder Membre
    22:15 modifié #2
    dans 1318330211:

    Bonjour je me heurte a un problème qui parait simple mais dont je comprends pas la source je m'explique. J'ai une date que je dois incrémenter 28 fois du coup dans un for j'appelle une de mes fonctions qui incrémente la date de départ de un jour multiplié par le compteur de mon "for":

    -(void)viewDidLoad{<br />&nbsp; &nbsp; [super viewDidLoad];<br />&nbsp; &nbsp; arrayMut = [[NSMutableArray alloc] init];<br />&nbsp; &nbsp; for (int i = 0 ; i&lt;28; i++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; NSString *dateinc = [self dateIncrementWithDate:@&quot;2011-10-10&quot; cpt:i];<br />&nbsp; &nbsp; &nbsp; &nbsp; [arrayMut addObject:dateinc];<br />&nbsp; &nbsp; }<br />}<br />-(NSString *)dateIncrementWithDate:(NSString *)dateStr cpt:(int)cpt{<br />&nbsp; &nbsp; NSDateFormatter *format = [[[NSDateFormatter alloc] init] autorelease];<br />&nbsp; &nbsp; [format setDateFormat:@&quot;yyyy-MM-dd&quot;];<br />&nbsp; &nbsp; NSDate *date = [format dateFromString:dateStr];<br />&nbsp; &nbsp; NSTimeInterval time = 24*3600*cpt;<br />&nbsp; &nbsp; NSDate *dateEnvoie = [[NSDate alloc] initWithTimeInterval:time sinceDate:date];<br />&nbsp; &nbsp; NSString *maDate = [format stringFromDate:dateEnvoie];<br />&nbsp; &nbsp; [dateEnvoie release];<br />&nbsp; &nbsp; return maDate;<br />}
    


    Dans mon tableau la fonction m'affiche deux fois la date 2011-10-30 et une seul fois toutes les autres date. Alors que dans mes NSLog date est toujours identique.

    Si jamais je modifie un peu mon code comme ça :

    -(void)viewDidLoad{<br />&nbsp; &nbsp; [super viewDidLoad];<br />&nbsp; &nbsp; arrayMut = [[NSMutableArray alloc] init];<br />&nbsp; &nbsp; for (int i = 0 ; i&lt;28; i++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; NSString *dateinc = [self dateIncrementWithDate:i];<br />&nbsp; &nbsp; &nbsp; &nbsp; [arrayMut addObject:dateinc];<br />&nbsp; &nbsp; }<br />}<br />-(NSString *)dateIncrementWithDate:(int)cpt{<br />&nbsp; &nbsp; NSDateFormatter *format = [[[NSDateFormatter alloc] init] autorelease];<br />&nbsp; &nbsp; [format setDateFormat:@&quot;yyyy-MM-dd&quot;];<br />&nbsp; &nbsp; NSTimeInterval time = 24*3600*cpt;<br />&nbsp; &nbsp; NSDate *dateEnvoie = [[NSDate alloc] initWithTimeInterval:time sinceDate:[NSDate date]];<br />&nbsp; &nbsp; NSString *maDate = [format stringFromDate:dateEnvoie];<br />&nbsp; &nbsp; [dateEnvoie release];<br />&nbsp; &nbsp; return maDate;<br />}
    


    La ça fonctionne bien j'ai toutes mes dates comme il faut. Je sais pas trop quoi faire pour régler le problème. Merci d'avance pour vos réponses


    Bonjour,

    Si tu veux ajouter une journée a une date tu as plus simple:

    <br />NSDate *now = [NSDate date];<br />int daysToAdd = 1;<br />NSDate *newDate1 = [now addTimeInterval:60*60*24*daysToAdd];<br />NSLog(@&quot;Nouvelle date: %@&quot;, newDate1);<br />
    


  • NasatyaNasatya Membre
    22:15 modifié #3
    Merci pour ta réponse c'est vrais que cette technique est plus lisible mais la je pars d'une string renvoyé par un script php je pense pas que ça changera grand chose a mon problème.

    Pour celles et ceux qui auront le même problème on a trouver une solution. C'est a cause du passage a l'heure d'hiver qui a lieu dans le mois d'octobre qui enlève une heure.

    Comme j'envoie juste une date sous forme yyyy-MM-dd je ne donne pas d'heure contrairement au [NSDate date] (c'est pour ça que cela fonctionnai pour ce cas la) du coup par défaut le NSDate s'initialise a yyyy-MM-(dd - 1) 22:00 (problème connu de l'objet date). Avec le changement d'heure ça donne yyyy-MM-(dd - 1) 21:00 et du coup quand le sdk rajoute les deux heures manquantes elle retrouve bien le yyyy-MM-(dd - 1) 23:00 et donc le jour dd-1 est affiché deux fois.

    Du coup on a résolu le problème en bricolant un peu cette ligne NSTimeInterval time = 24*3600*cpt; en NSTimeInterval time = 24*3600*cpt+3600;
  • AliGatorAliGator Membre, Modérateur
    22:15 modifié #4
    C'est tout à  fait normal (et le fait que l'objet date s'initialise à  22h n'est pas un "problème connu", c'est également qqch de normal)

    1) Une NSDate porte l'information de TimeZone (fuseau horaire) or dans le fuseau horaire de Paris, on est en GMT+2. Et quand tu demandes d'afficher une date dans la console (NSLog) elle s'affiche avec l'heure "22:00:00 +0200"... ce qui est bien exactement la même date et heure que l'heure "24:00:00 +0000" (heure GMT).

    C'est juste que tu n'as pas pris en considération que les NSDate portaient l'information de fuseau horaire. Là  actuellement il est 15h52 dans le fuseau horaire GMT+2 mais il est aussi 13h52 dans le fuseau horaire GMT, pourtant c'est le même moment dans le temps.

    Pour le passage de l'heure d'été à  l'heure d'hiver c'est normal aussi que ça te fasse déconner sur tes dates.
    Il y a de nombreuses remarques à  faire sur ton code :

    1) Tu initialises un NSDateFormatter à  chaque fois. Ca marche, mais c'est coûteux et dommage. Tu devrais plutôt l'initialiser une fois pour toutes à  l'extérieur de ta boucle for.

    2) Dans l'absolu, tu devrais également garder dans une variable la date [tt][NSDate date][/tt]. D'une part pour éviter d'avoir à  le recalculer/reconstruire à  chaque fois, et si on veut être pointilleux, si jamais ta boucle for est un peu longue et que le calcul se fait autour de minuit, les premières dates pourraient être basées sur un jour J et les dernières sur J+1 (même si en pratique ça n'arrivera jamais, soyons francs, les vitesses de calcul sont telles qu'il faudrait vraiment ne pas avoir de veine, mais bon)

    3) Mais surtout, si tu veux manipuler les composantes des NSDates, c'est à  dire manipuler des jours, des mois, ajouter des jours (y compris en ne se faisant pas avoir par les décalages horaires donc en ajoutant bien des vrais jours et pas 24 heures à  une date), utilise la classe [tt]NSDateComponents[/tt]

    4) Et de manière générale, va lire le "Date & Time Programming Guide" dans la doc Apple qui va te permettre de bien mieux maitriser ces concepts et tout savoir sur les dates et heures, leurs subtilités et comment les manipuler dans Cocoa.
  • NasatyaNasatya Membre
    22:15 modifié #5
    Merci pour ta réponse si complète... Tu m'impressionnes à  chaque fois.Tu soulignes beaucoup de problème dans mon code il est vrais que je devrais le changer. Pour le "problème connu" j'ai fait un raccourci un peu abrupte je te le concède je voulais dire par la que la solution était prise en compte dans le sdk et que beaucoup de post sur ce forum et ailleurs parlent de ce sujet. 

    pour ma défense :

    1 ) je suis tout a fait d'accord avec toi et je change ça dès demain dans mon code ;)

    2 ) Le NSDate n'existe pas dans mon programme j'ai codé un "simple" rapidement pour faire mes tests. Les boucles ne se feront qu'une seul fois a l'ouverture de l'application et n'excéderont pas 28 itérations ça me semble pas être un réel souci pour un outil tel que l'iPhone (je ne dis pas pour autant que l'optimisation n'est pas importante évidemment).

    3 ) Je n'ai pas trop compris la classe NSDateComponents comme le projet sur lequel je travail est a rendre un peu dans l'urgence je préférais allé au plus rapide mais je comblerais mes lacunes plus tard c'est important de savoir bien gérer les date dans une application.

    4 ) Je suis allé voir la documentation apple c'est devenu un réflexe et j'y repartirais pour comme tu le dis mieux maitriser les concepts de la programmation iPhone.

    Je te remercie en tout cas de ta réponse toutes les aides sont bienvenue pour apprendre merci encore.
Connectez-vous ou Inscrivez-vous pour répondre.