IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

tm_mday > 31 passé dans une struct tm pour mktime : Valide ! Pourquoi ?


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2007
    Messages : 128
    Points : 70
    Points
    70
    Par défaut tm_mday > 31 passé dans une struct tm pour mktime : Valide ! Pourquoi ?
    Bonjour,

    J'ai une question sur la méthode mktime de <ctime>.

    Voici le code qui pose problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        time_t rawTime = 0, time = 0;
        struct tm *t =  localtime (&rawTime);
        t->tm_sec = 0;
        t->tm_min = 0;
        t->tm_hour = 0;
        t->tm_mday = 50;
        t->tm_mon = 11;
        t->tm_year = 100;
        time = mktime(t);
    Normalement time devrait être égal à -1(sur la dernière ligne en rouge) vu que je tente de convertir la date 50ième jour du mois de décembre 2070 :
    If the calendar time cannot be represented, a value of -1 is returned.
    Mais ce n'est pas le cas. Pourquoi ?
    Je n'arrive pas à trouver un semblant de réponses sur le net


    Edit : En faisant des recherches et en utilisant des mots exotiques sur google, j'ai réussi à trouver la réponse à ma question.
    C'est mktime qui ajuste les valeurs de la structure. Par ex le 32 janvier sera compris comme le 1 février..
    Et le 29 février 2013 sera compris comme le 1 mars 2013.....

    Du coup, ça ne m'arrange pas.
    Effectivement, pour vérifier une date :
    * je faisais appel à localtime pour me fournir une struct tm valide
    * je modifiais la struct tm en la remplissant de la date à vérifier
    * je donnais la struct tm à mktime et vérifiais si le retour == -1 pour voir si la date était correcte..
    N'existe-t-il pas une méthode tel que mktime mais qui ne chipote pas lors de la conversion ? Donc qui fait stricto sensu la conversion de la date qu'on lui donne et puis c'est tout.

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Si les variables sont ajustées quand elles ne respectent pas les bornes, tu peux peut-être ajouter une comparaison pour détecter l'ajustement en question après l'appel.

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    De manière générale, ou bien tu utilises localtime pour te donner une structure complétée avec les valeur adéquates, mais que tu n'utilise que pour récupérer les données qu'elle contient, ou bien, tu crées toi-même la structure en question, à charge pour toi de veiller à ce que les valeurs que tu y indiques soient cohérentes.

    Ceci dit, la vérification de la validité d'une date est particulièrement simple, étant donné qu'elle peut se limiter à deux fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    bool isBisextile(int annee){
        if( annee % 4){ 
            if(annee % 100){
                if(annee % 400){
                    return true;
                }
                return false;
            }
            return true;
        }
        return false;
    }
    bool isCorrectDate(int day, int month, int year){
        static int numberOfDays[12]={31,0,31,30,31,30,31,31,30,31,30,31};
        if(day <31 || day > 1 )
            return false;
        if(month == 2){
            if(isBissextile(year){
                numberOfDays[1] = 29;
            }
            else{
                numberOfDays[1] = 28;
            }
        }
        return day <= numberOfDays[mounth - 1];
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ceci dit, la vérification de la validité d'une date est particulièrement simple, étant donné qu'elle peut se limiter à deux fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    bool isBisextile(int annee){
        if( annee % 4){ 
            if(annee % 100){
                if(annee % 400){
                    return true;
                }
                return false;
            }
            return true;
        }
        return false;
    }
    bool isCorrectDate(int day, int month, int year){
        static int numberOfDays[12]={31,0,31,30,31,30,31,31,30,31,30,31};
        if(day <31 || day > 1 )
            return false;
        if(month == 2){
            if(isBissextile(year){
                numberOfDays[1] = 29;
            }
            else{
                numberOfDays[1] = 28;
            }
        }
        return day <= numberOfDays[mounth - 1];
    }
    Quel dommage de devoir réimplémenter la roue...le traitement de dates est un truc si standard et tellement moins simple qu'il n'y paraît...heureusement que ce n'est que la date et non l'heure, car là il y a de quoi s'arrahcer les cheveux.

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par therwald Voir le message
    Quel dommage de devoir réimplémenter la roue...le traitement de dates est un truc si standard et tellement moins simple qu'il n'y paraît...heureusement que ce n'est que la date et non l'heure, car là il y a de quoi s'arrahcer les cheveux.
    En effet.

    Mais, à l'heure actuelle, il n'y a encore rien de standard pour la gestion des dates.

    Ceci dit, pour éviter d'avoir à réinventer la roue on peut proposer de passer par boost::date_time.

    Toute la question (plus ou moins théorique) étant de savoir s'il est préférable de se contenter d'implémenter deux fonctions sommes toutes triviales pour éviter une dépendance supplémentaire ou s'il vaut mieux payer le prix de cette dépendance car on manipulera des dates et des heures de manière régulière et plus poussée

    Dans certains cas, l'utilisation de boost::date_time est très largement justifiée, dans d'autres, si le but est de "valider" une date mais qu'il n'y a pas d'autres manipulations à faire, est-ce que cela en vaut réellement la peine Chacun verra midi à sa porte
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2007
    Messages : 128
    Points : 70
    Points
    70
    Par défaut
    Merci pour vos réponses.
    Ce qui m'aurait intéressé c'est une fonction standard..
    Je pense que je vais me contenter de vérifier la date avant de l'envoyer à mktime.

    Bien à vous

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2007
    Messages : 128
    Points : 70
    Points
    70
    Par défaut
    Je rajoute une question à mon topic.
    Je viens de remarquer un truc que je n'avais pas vu au départ.
    Dans une struct tm, le membre tm_year doit être une valeur supérieur ou égale à 1900. Or mktime renvoie le nombre de secondes depuis 1970..
    Et si je lui mets 1950 à tm_year, quelqu'un peut-il me dire où je peux trouver une documentation qui me dise qu'est-ce que mktime va me renvoyer ?
    J'ai rien trouvé, j'ai bien fais 5-10 man sur le net..

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    http://lmgtfy.com/?q=mktime+C%2B%2B

    Et pourquoi ne pas faire le test tout simplement ?
    Si la valeur n'est pas représentable, la doc indique que ça retourne -1

    Btw, le paramètre passé à mktime n'est pas constant, mktime le modifie pour le rendre valide.

    Enfin, je ne fais que répéter la doc.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2007
    Messages : 128
    Points : 70
    Points
    70
    Par défaut
    Ceci est une date erronée : 43/12/2013. Pourtant mktime sait le représenter, car il le modifie pour s'adapter.
    Dès lors, on peut se dire qu'il va s'adapter à une date du style x/y/1950. Rien est dit dans les man que j'ai consulté :
    http://www.cplusplus.com/reference/ctime/mktime/
    http://www.linux-france.org/article/...asctime-3.html
    http://linux.die.net/man/3/mktime
    http://www.manpagez.com/man/3/mktime/
    et j'en passe.


    Vous ne répondez donc pas à ma question.
    Ce que je demande, c'est :
    Quelqu'un peut-il me dire où je peux trouver une documentation qui me dise qu'est-ce que mktime va me renvoyer dans le cas où je met une année comprise entre 1900 et 1970 ?

    Moi, dans ma logique, je me dis :
    * mktime renvoie le nombre de sec depuis 1970.
    * du coup, toute date antérieur ne peut pas être représentée => -1
    * cependant, sait-il s'adapter en se disant : ha bah, il a rentré 1950, je vais mettre 1970 à la place.
    > Je n'ai aucune doc qui me dise ce que mktime va faire pour une année comprise entre 1900 et 1970.

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Que ne comprends-tu pas dans la doc quand on y lit très clairement
    If the calendar time cannot be represented, a value of -1 is returned.
    Ou bien, ne peux-tu pas "perdre" à peu près 30s pour faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <ctime>
    void main()
    {
    	tm t;
    	t.tm_year = 1950;
    	time_t r = mktime(&t);
    	std::cout<<r<<std::endl;
    }
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2007
    Messages : 128
    Points : 70
    Points
    70
    Par défaut
    J'ai déjà regardé à sa valeur de retour, je sais qu'elle est de -1. Mais il ne faut pas faire d'une application une théorie.. cela parait évident, mais bon.

    Je vois bien que tu n'as pas compris ma question.
    Je la répète. Une date incorrecte d'un point de vue logique est par ex 41 décembre 2013 : Elle ne devrait en théorie pas être représentable !
    Cette date est néanmoins convertie en une date représentable par mktime.
    Ma question est de savoir QUE FAIT MKTIME quand il rencontre une année du style 1950. Il la ramène à 1970 pour que ce soit représentable ? Il traite cela comme une erreur ? Quelle est la doc qui me dit que cela va être traiter comme une erreur plutôt qu'un autre traitement ?
    Mince, je ne peux pas être plus claire.

  12. #12
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    3° et dernier essai.

    Citation Envoyé par zizoufoot Voir le message
    J'ai déjà regardé à sa valeur de retour, je sais qu'elle est de -1. Mais il ne faut pas faire d'une application une théorie.. cela parait évident, mais bon.
    Donc tu ne sais pas lire la doc ? Ou tu fais juste preuve de tellement de mauvaise foie que ça en devient ridicule ?
    C'est pas une application c'est un exemple de la doc. Et pas une théorie fumeuse, contrairement à tes propos.

    Citation Envoyé par zizoufoot Voir le message
    Je la répète. Une date incorrecte d'un point de vue logique est par ex 41 décembre 2013 : Elle ne devrait en théorie pas être représentable !
    Avec mktime si parce que mktime modifie la tm passée en paramètre pour ajuster les champs à une valeur existante.

    Citation Envoyé par zizoufoot Voir le message
    Ma question est de savoir QUE FAIT MKTIME quand il rencontre une année du style 1950. Il la ramène à 1970 pour que ce soit représentable ? Il traite cela comme une erreur ? Quelle est la doc qui me dit que cela va être traiter comme une erreur plutôt qu'un autre traitement ?
    Mince, je ne peux pas être plus claire.
    Et encore une fois, la doc est on ne peut plus claire, et bien plus claire que toi qui ne semble pas vouloir l'assimiler.
    Morceaux choisis
    the values of the other members are interpreted even if out of their valid ranges For example, tm_mday may contain values above 31, which are interpreted accordingly as the days that follow the last day of the selected month.
    automatically adjusts the values of the members of timeptr if they are off-range
    Return Value
    A time_t value corresponding to the calendar time passed as argument.
    If the calendar time cannot be represented, a value of -1 is returned.
    time_t, comme ça a été dit plus haut
    integral value representing the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC (i.e., a unix timestamp)
    Partant de là, il est évident et trivial de savoir qu'une date de 1950 n'est pas représentable, tout le monde l'aura déjà compris, et on tombe donc dans le cas clairement défini par la doc
    If the calendar time cannot be represented, a value of -1 is returned.
    et, sur toutes les architectures que j'ai rencontré jusque là, tm n'est pas modifié.

    Si la doc ne te satisfait pas, alors personne ne peut rien pour toi.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2007
    Messages : 128
    Points : 70
    Points
    70
    Par défaut
    Donc tu ne sais pas lire la doc ? Ou tu fais juste preuve de tellement de mauvaise foie que ça en devient ridicule ?
    C'est pas une application c'est un exemple de la doc. Et pas une théorie fumeuse, contrairement à tes propos.
    Voilà, ce que tu as mis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <ctime>
    void main()
    {
    	tm t;
    	t.tm_year = 1950;
    	time_t r = mktime(&t);
    	std::cout<<r<<std::endl;
    }
    Ceci est donc un exemple de la doc.
    Bien, montre moi la doc associé ? Sache que dans tm_year, on ne met que year-1900, il s'agit donc d'un code personnel ou qui appartient à un ahuri sur internet.
    Donc, je vais bien prendre cet exemple comme théorie fumeuse !

    Avec mktime si parce que mktime modifie la tm passée en paramètre pour ajuster les champs à une valeur existante.
    Je le sais ! C'est pourquoi je cherche à savoir si il ne ferait pas également pareil pour une année comprise entre 1900 et 1970. Quelle est la doc qui dit ? :
    Pour une année comprise entre 1900 et 1970, mktime n'interprète pas le champ et renvoie -1.
    Si tu as la doc, montre la moi, fais moi l'extrait. C'est tout ce que je demande ! Par défaut, je ne crois que ce qui est dans une doc et non des test perso.

    Sinon, le reste de tes commentaires n'ont pas besoin d'être commentés. Tu n'as pas saisis ma question.
    Tout ce que tu écris je le sais, je peux le tester. Mais aucune doc(tout du moins, celles que j'ai lu) ne dit explicitement ce qu'il se passe quand une date entre 1900 et 1970 est fournie à mktime :
    * Est-ce que mktime s'adapte et change la valeur en 1970 ? On sait que non via les test, mais ce sont des test.. Où est-il écrit qu'il ne s'adapte pas et renvoie simplement -1 ?

    Je vais donner des exemples.
    * Si on fournit -1 à tm_mday, de tête, il va récupérer le mois et dire simplement que le jour = 31/30/29/28.
    * Si on fournit 30/02/2012, il va interprété cela comme 01/03/2013
    Ma question :
    * Si on fournit 10/10/1950, est-ce qu'il va l'interprété pour pouvoir retourner un time_t correcte ou va-t-il renvoyer -1 ?
    On sait par les test qu'il renvoit -1, mais ce sont des test. Où est-il écrit dans une doc que pour une date entre 1900 et 1970, il ne va pas l’interprété et va simplement renvoyé -1 ???

    Je ne peux être plus clair, même ma compagne a compris..
    Dans ce message, j'ai réexpliqué le même point de vue de x manière différentes. Désolé pour le(s) lecteur(s) qui pourraient trouver le post redondant.

  14. #14
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Ce que tu n'as pas compris c'est que mktime ne modifie PAS la date que tu as passée. Il ajuste les champs de manière à représenter. LA MEME DATE avec des valeurs de champs valide. Par exemple, 32 janvier devient 1er février.
    1950 est hors de la période couverte par les timestamps unix, qui commence le 01/01/1970 donc une date en 1950 est non representable.

Discussions similaires

  1. Mot de passe dans une archive
    Par Jibees dans le forum Linux
    Réponses: 1
    Dernier message: 04/12/2006, 23h08
  2. Réponses: 2
    Dernier message: 22/02/2006, 11h18
  3. Réponses: 2
    Dernier message: 19/01/2006, 21h59
  4. mettre les termes d'un string dans une struct
    Par grand's dans le forum SL & STL
    Réponses: 17
    Dernier message: 29/11/2004, 17h43
  5. sécuriser le mot de passe dans une page asp
    Par Redouane dans le forum ASP
    Réponses: 2
    Dernier message: 10/03/2004, 21h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo