Dernier jour du mois

olofolof Membre
23:07 modifié dans API AppKit #1
Question peut-être un peu bête, mais je sèche.

Je suis en train de dessiner un calendrier du mois courant. Comment faire pour trouver le dernier jour d'un mois donné ?

Mai -> 31


Merci  !

Réponses

  • schlumschlum Membre
    23:07 modifié #2
    Euh... Avec un tableau ?
    31,28,31,30,31,30,31,31,30,31,30,31
    (et ajouter 1 à  février pour tous les multiples de 400 ou les multiples de 4 non multiples de 100)
  • ChachaChacha Membre
    23:07 modifié #3
    Si tu veux, je peux te proposer un calcul s'appuyant sur NSCalendarDate :

    <br /><br />NSCalendarDate* date = ... //une date quelconque dans le mois à  tester<br /><br />//on calcule la date du premier jour du mois suivant<br />//pour cela on prend le premier jour du mois à  tester, et on ajoute un mois<br />NSCalendarDate* nextMonth =<br />&nbsp; [[NSCalendarDate dateWithYear:[date yearOfCommonEra]<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; month:[date monthOfYear] day:1 hour:0 minute:0 second:0<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;timeZone:[NSTimeZone defaultTimeZone]]<br />&nbsp; &nbsp; dateByAddingYears:0 months:1 days:0 hours:0 minutes:0 seconds:0];<br /><br />//on calcule combien de jours entre maintenant et le 1 du mois suivant<br />int nbDaysbeforeNextMonth = [nextMonth dayOfCommonEra]-[date dayOfCommonEra];<br /><br />//on en déduit le nombre de jours du mois à  tester<br />int nbDaysInMonth = [date dayOfMonth]+nbDaysbeforeNextMonth-1;<br />
    


    Ouf, je n'aimerais pas faire les calculs moi-même !

    +
    Chacha
  • olofolof Membre
    23:07 modifié #4
    Merci Chacha, c'est bien dans cette direction que je voulais aller, mais je n'avais pas vu la méthode 'dateByAddingYears'.

    Et si jamais, on peut faire un poil plus simple. Au lien de passer par le nombre de jour, on cherche le permier jour du mois suivant et on lui "ajoute" -1 jour.

    <br />NSCalendarDate* vDate = ... //une date quelconque dans le mois à  tester<br /><br />NSCalendarDate *vDateDernierJour = [[NSCalendarDate dateWithYear:[vDate yearOfCommonEra]<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; month:[vDate monthOfYear]+1 day:1 hour:0minute:0 second:0 timeZone:[vDate timeZone]]<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  dateByAddingYears:0 months:0 days:-1 hours:0 minutes:0 seconds:0];<br /><br />
    
  • ChachaChacha Membre
    juin 2007 modifié #5
    dans 1180639756:

    Au lien de passer par le nombre de jour, on cherche le permier jour du mois suivant et on lui "ajoute" -1 jour.

    Woah, c'est osé ! Enfin, s'ils ont prévu des "int" c'est que ça doit marcher. Pas bête !

    +
    Chacha
    [edit]
    En fait c'est écrit noir sur blanc dans la doc...
  • schlumschlum Membre
    23:07 modifié #6
    Hum, je crois que j'ai pas trop compris la question alors  :brule:

    C'est le jour de la semaine qu'on cherche ??
  • olofolof Membre
    23:07 modifié #7
    dans 1180649147:

    Hum, je crois que j'ai pas trop compris la question alors  :brule:

    C'est le jour de la semaine qu'on cherche ??


    Je cherchais (vu que c'est bon maintenant) la dernière date d'un mois donné. Mai 2007 -> 31.5.2007 par exemple.
  • schlumschlum Membre
    23:07 modifié #8
    Mais là  où y a quelque-chose qui m'échappe, c'est que c'est un truc fixe ça non ?  :o

    Tous les mois de Mai ont 31 jours, donc Mai **** -> 31
    Pareil pour tous les autres mois, sauf Février qui a 28 jours ou 29 les années bissextiles (multiples de 400 ou multiples de 4 non multiples de 100)

    Pourquoi donc faire des calculs aussi complexes avec deux objets NSCalendarDate là  où un tableau statique suffit ??
  • ChachaChacha Membre
    23:07 modifié #9
    dans 1180682242:

    Mais là  où y a quelque-chose qui m'échappe, c'est que c'est un truc fixe ça non ?  :o
    Pourquoi donc faire des calculs aussi complexes avec deux objets NSCalendarDate là  où un tableau statique suffit ??


    J'ai envie de dire : "moins de code = moins de bugs". En fait, avec NSCalendarDate, c'est réglé en une ligne de code (création de la date, enlever un jour,récupérer le dayOfMonth).
    Après, tu as tout à  fait raison, ce n'est pas tellement plus compliqué de le faire avec un tableau...

    +
    Chacha
  • schlumschlum Membre
    juin 2007 modifié #10
    dans 1180683808:

    dans 1180682242:

    Mais là  où y a quelque-chose qui m'échappe, c'est que c'est un truc fixe ça non ?  :o
    Pourquoi donc faire des calculs aussi complexes avec deux objets NSCalendarDate là  où un tableau statique suffit ??


    J'ai envie de dire : "moins de code = moins de bugs". En fait, avec NSCalendarDate, c'est réglé en une ligne de code (création de la date, enlever un jour,récupérer le dayOfMonth).
    Après, tu as tout à  fait raison, ce n'est pas tellement plus compliqué de le faire avec un tableau...

    +
    Chacha

    Ben moi j'ai envie de dire "moins de passage par des objets 'boà®tes noires' = moins de bugs et plus d'optimisation"  :P (dans la limite du raisonnable bien sûr... Je ne vais pas m'amuser à  aller recoder NSString !)
    Là  passer par un NSCalendarDate c'est pourquoi faire simple quand on peut faire compliqué  ???

    Aller calculer des différences de dates avec des timeZone et compagnie pour trouver combien de jours a un mois, ça me donne mal à  la tête  ;D

    Et puis faut pas oublier que dans "Objective-C", il y a "C" :P
  • schlumschlum Membre
    23:07 modifié #11
    Bon, je vais donner du code quand même...

        int nbDays[12] = {31,28,31,30,31,30,31,31,30,31,30,31};<br />    int nbDay = nbDays[month-1];<br />    if(month==2&amp;&amp;((year%400)==0||((year%4)==0&amp;&amp;(year%100)!=0)))<br />        ++nbDay;
    


    Je crois que si on compte en nombre de caractères, y a pas photo :P (sans parler d'une comparaison en terme de simplicité...)
  • AliGatorAliGator Membre, Modérateur
    23:07 modifié #12
    Oui mais justement schlum ton code montre que c'est parfois mieux de passer par les classes prévues dans Cocoa.

    En effet si on raisonne vite fait sans trop connaà®tre le domaine, on peut se dire qu'on fait un bête tableau à  12 valeurs et on prend la bonne valeur. Point barre. Et là , on utilise, on teste un peu, et oups, on s'aperçoit qu'on a oublié les années bisextiles. Bon alors on rajoute. Comme on s'y connais pas trop, on rajoute un jours si l'année est multiple de 4 et point barre... et on oublie les cas particuliers des multiples de 100 non multiples de 400... (ce qui n'est pas qqch que tout le monde connait, entre nous).

    Bref, à  le faire à  la main, il faut penser à  tous les cas particuliers... même quand on pense qu'il n'y en a pas (ici le problème paraà®t simple alors qu'il y a quand même des cas un peu spéciaux, par exemple). Alors qu'avec NSCalendarDate, on est sûr que toutes les subtilités sont prévues.

    D'ailleurs c'est dommage qu'on ne puisse passer que des unsigned dans le constructeur. En PHP par exemple on peut demander le -5/14/2007 et il va nous créer la date qui est "6 jours avant le 01/14/2007" soit 6 jours avant le 01/02/2008... soit le 26/01/2008. Très pratique pour ce genre de cas (passer au mois suivant ou reculer d'un certain nombre de jours sans ce soucier des bounds 1-12 pour les mois ou 1-N pour les jours).
  • schlumschlum Membre
    23:07 modifié #13
    Je suis d'accord que pour travailler sur des offsets de jours, calculer les jours de la semaine et autres joyeusetés, les classes sont très pratiques.

    Pour le cas présent, je persiste à  dire que c'est la presse hydraulique pour écraser une mouche.

    Surtout que ceux qui ont programmé ces classes sont humains comme nous et ont aussi pu laisser des bugs (de domaine d'action très restreint, cas rares etc. certes).
  • 23:07 modifié #14
    C'est de l'overkill si tu veux te limiter au calendrier grégorien, mais il ne me semble pas qu'il soit utilisé par tout le monde. En passant par les classes, tu as au moins la garantie que le code fonctionnera avec tous les calendriers.
  • schlumschlum Membre
    juin 2007 modifié #15
    NSCalendarDate is a public subclass of NSDate that represents concrete date objects and performs date computations based on the Gregorian calendar. These objects associate a time interval with a time zone and are especially suited for representing and manipulating dates according to western calendrical systems.


    Encore "overkill" ?  :) J'ai déjà  oublié ce que ça veut dire   :fouf):

    Effectivement, ça serait intéressant de savoir comment on gère un calendrier Chinois ou autre... (à  mon avis, il faut se faire sa propre classe NSDate).
  • 23:07 modifié #16
    ça veut dire "presse hydraulique pour écraser une mouche" (c'est plus court).

    Mais bon, comme tu m'as grillé sur ce coup j'allais justement écrire ce que tu as mis en citation. Mais en passant par NSCalendar, on peut jouer avec les différents calendriers.
  • schlumschlum Membre
    23:07 modifié #17
    Ouais... Mais c'est pas la joie  :crackboom:-

    In a calendar, day, week, weekday, month, and year numbers are generally 1-based, but there may be calendar-specific exceptions. Ordinal numbers, where they occur, are 1-based. Some calendars represented by this API may have to map their basic unit concepts into year/month/week/day/... nomenclature. For example, a calendar composed of 4 quarters in a year instead of 12 months uses the “month” unit to represent quarters. The particular values of the unit are defined by each calendar, and are not necessarily “consistent with” or have a “correspondence with,” values for that unit in another calendar.


    Il faut mapper le système du calendrier sur un système jour/semaine/mois/année...

    Autant dire que c'est inutilisable pour pas mal de calendriers.

    En plus, il faut coder soi même les calendriers ; il n'y a pas les classes toutes faites ; le seul truc qu'il gère automatiquement est le calendrier Julien qui n'est plus utilisé nulle part...
  • juin 2007 modifié #18
    Non, non. Il y a d'autres calendriers qui sont gérés par le système: NSGregorianCalendar,NSBuddhistCalendar, NSChineseCalendar, NSHebrewCalendar, NSIslamicCalendar, NSIslamicCivilCalendar, NSJapaneseCalendar.

    Mais de toute façon, à  la limite, on s'en fout:
    - en général, le seul calendrier qui compte c'est le calendrier choisi par l'utilisateur (qui est [tt][NSCalendar currentCalendar][/tt].
    - même si le calendrier qu'on veut gérer n'est pas géré pour le moment, ça ne veut pas dire qu'il le sera jamais: un tel code l'avantage de toujours rester valable.

    Pour répondre à  la question:
    [tt]
    NSDate *date = [NSDate date];
    NSCalendar *cal = [NSCalendar currentCalendar];
    NSDateComponents *dateComponents = [cal components:NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit
    fromDate:date];
    [dateComponents setMonth:[dateComponents month]+1];
    [dateComponents setDay:-1];

    dateComponents = [cal components:NSDayCalendarUnit
    fromDate:[cal dateFromComponents:dateComponents]];
    NSLog(@%i,[dateComponents day]+1);
    [/tt]

    L'idéal étant bien entendu de ranger ça dans une petite catégorie de NSDate pour que le code reste lisible (je le dis car beaucoup de gens ne pensent pas spontanément à  créer des catégories pour "quelques lignes").
  • schlumschlum Membre
    23:07 modifié #19
    Merci pour l'info !  8--)

    Défini dans NSLocale.h

    // Values for NSCalendar identifiers (not the NSLocaleCalendar property key)<br />FOUNDATION_EXPORT NSString * const NSGregorianCalendar;<br />FOUNDATION_EXPORT NSString * const NSBuddhistCalendar;<br />FOUNDATION_EXPORT NSString * const NSChineseCalendar;<br />FOUNDATION_EXPORT NSString * const NSHebrewCalendar;<br />FOUNDATION_EXPORT NSString * const NSIslamicCalendar;<br />FOUNDATION_EXPORT NSString * const NSIslamicCivilCalendar;<br />FOUNDATION_EXPORT NSString * const NSJapaneseCalendar;
    


    Par contre, je ne sais pas si le concept de "nombre de jours dans un mois" ou "dernier jour d'un mois" existe avec ces calendriers...
  • juin 2007 modifié #20
    Bien sur, le mois est défini comme étant une "subdivision majeure de l'année", qui compte toujours un certain nombre de jours (dont la définition est assez semblable suivant les calendriers). Maintenant, le nombre de subdivisions que comporte l'année n'a pas beaucoup d'importance, ni même leur durée, comme on travaille en relatif et toujours dans le même calendrier, pas de souci.
Connectez-vous ou Inscrivez-vous pour répondre.