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 :

Utilisation de mktime: problème d'heure d'été et hiver


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 90
    Par défaut Utilisation de mktime: problème d'heure d'été et hiver
    bonjour,

    dans un prog C que j'ai fait, je manipule des dates sous forme time_t et struct tm. Je me suis pas mal renseigné sur toutes les fonctions qui les manipulent et sur les particularités de ces structures, mais j'ai toujours un problème. Jusqu'à maintenant, mon prog fonctionnait très bien, mais depuis le changement d'heure, il marche plus, et depuis je cherche à résoudre le problème sans succès.

    Pourtant, les opérations que j'effectue peuvent se résumer à ça:

    * je rentre à la main une date, et applique les corrections nécessaire pour en faire un objet struct tm (mois-1, année-1900, des trucs comme ça).
    * J'en fais un objet de type time_t avec mktime
    * Je l'affiche avec ctime

    --> si la date est dans le créneau "été", ça marche, la date affichée est la bonne, si elle est en hiver, la date possède une heure de moins que ce que je voulais. Je pensais que le paramètre tm_isdst de struct tm arrangerait le problème, mais que neni, ça enlève au contraire une heure à tout le monde.

    En fait, je fais tout ça pour pouvoir faire un diff entre la date entrée et la date local récupérée avec la fonction time, donc il me faudrait pouvoir être sûr de mettre ces deux dates au même format, GMT ou local peu importe puisque je fais un diff, histoire d'avoir quelque chose qui marche hiver comme été. Je n'ai toujours pas trouvé comment faire.

    Si vous avez une idée, je suis preneur...

    merci !

  2. #2
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Salut,

    Tu peux construire tes struct tm avec gmtime au lieu de localtime, ça te retournera la date gmt
    Pour la date saisie, il faut se mettre d'accord si c'est une date gmt où une date locale.
    Si c'est un date locale : conversion en timestamp avec mktime (sans toucher à isdst) puis reconversion en struct tm avec gmtime

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 90
    Par défaut
    salut,

    Je n'utilise ni localtime ni gmtime, puisque je n'effectue aucune conversion time_t --> struct tm: ma comparaison entre la date que je rentre et la date système se faisant avec diff, donc sur des objets time_t.

    Je rentre la date à la main (en heure local donc), et je l'injecte direct dans les variables de mon objet struct tm. Tout le problème réside donc dans la conversion de cet objet struct tm --> time_t pour la comparaison finale. J'utilise pour cela mktime, avec isdst à 0, et j'ai le problème dont je parle dans mon premier post: si la date que j'entre est en hiver (par ex le 25 dec), alors, après application de mktime, j'obtient 25 dec mais l'heure possède une heure de moins. Si la date est en été (17 juillet), alors, après application de mktime, j'obtient une date cohérente...

  4. #4
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Ah oki,
    Dans ce cas là, si tu n'as pas besoin de l'heure (juste de la date), en general j'initialise l'heure à autre chose que minuit (genre 6h du mat), comme ça ya plus de probleme de changement d'heure

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 90
    Par défaut
    oh que si je me sers de l'heure, quand je dis date c'est pour dire date + heure+min+sec et tout et tout
    C'est bien pour ça que mon problème d'heure m'embete, sinon je m'en soucierais pas !

  6. #6
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Ah ok ,)
    Au pire mktime -> gmtime -> mktime ?
    Je sais pas

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    90
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 90
    Par défaut
    oui, j'avais pensé à ce genre de bidouille, et apparemment ce genre de manip me permet d'avoir ma date avec deux heures de retard hiver comme été, ce qui fait que je peux ensuite ajouter deux heures et c'est bon.
    Avec localtime à la place de gmtime, ça fait pareil, mais avec une heure de retard (hiver comme été aussi)...

    Bon ça marche, mais quand même, je suis étonné qu'une opération aussi bateau ne permette pas de prendre en compte plus facilement le temps local, je reste un peu sur ma faim là...

    merci à toi !

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Février 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 24
    Par défaut
    Bonjour,

    Je sais que ce post date d'un an, mais je suis tombé dessus en faisait une recherche sur le même problème. Ce post ne m'a au final pas beaucoup aidé, mais j'ai pu résoudre mon problème, et comprendre comment fonctionnent mktime et le flag isdst.

    Je note donc mes conclusions ici afin que d'autres, confrontés au même problème, puissent trouver une réponse qui les satisfasse.

    Voila : le flag isdst indique si la date rentrée dans la structure struct_tm a été incrémentée de 1H pour tenir compte de l'heure d'été.

    Donc si la date T est une date d'hiver, et
    que isdst=0, ça signifie que la date n'a pas eu le +1h (normal puisque c'est une date d'hiver). le recours à mktime donnera donc l'heure T.
    que isdst=1, ça signifie que la date a eu le +1h (donc que la date entrée dans la structure est toujours en heure d'été alors qu'on est en hiver). le recours à mktime donnera donc l'heure T-1, afin d'effectuer le passage à l'heure d'hiver.

    Si la date T est une date d'été, et
    que isdst=0, ça signifie que la date n'a pas eu le +1h (oublie du passage à l'heure d'été par exemple). le recours à mktime donnera l'heure T+1
    que isdst=1, ça signifie que la date a eu le +1h (l'heure est "à l'heure d'été"). Le recours à mktime donnera bien l'heure T.


    Voila pour le fonctionnement de mktime et du flag isdst.

    Donc dans le cas d'une utilisation de struct_tm, et de mktime comme le fait casier, si on suppose que l'utilisateur entre une date correcte vis à vis de la saison (heure d'été ou d'hiver), alors il faut initialiser dynamiquement le flag isdst à 0 ou 1 en fonction de la date entrée par l'utilisateur. (0 si c'est une date d'hiver, 1 si c'est une date d'été).


    Vérification de l'heure d'été / d'hiver :
    Le changement d'heure ne s'effectuant pas à date fixe d'année en année (c'est le dernier dimanche de mars ou octobre), determiner si une date entre dans la catégorie été ou hiver peut poser problème.

    Voici une méthode que j'ai trouvé sur le forum futura-sciences ( http://forums.futura-sciences.com/thread36243.html ) qui permet de trouver le jour du changement d'heure :
    Cette méthode consiste à trouver quel est le jour de la semaine qui correspond au 31 mars/octobre, et en déduire de combien de jour il faut reculer pour tomber sur dimanche.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    La variable j doit être renseignée: 31 pour ce qui nous interresse
    la variable m est le mois
    a est l'année.
     
    m = m - 2: If m < 1 Then m = m + 12: a = a - 1
    siecle = Int(a / 100)
    a = a - (siecle * 100)
    b = Int(2.6 * m - 0.19) + j + a + Int(a / 4) + Int(siecle / 4) - siecle * 2
    jour = Int((b / 7 - Int(b / 7)) * 7 + 0.1)
    Voila, en espérant avoir été suffisament clair, et que cela sera utile

    Xtatic

  9. #9
    Membre confirmé
    Homme Profil pro
    Consultant
    Inscrit en
    Avril 2006
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Avril 2006
    Messages : 92
    Par défaut
    pour ce qui chercherais encore la solution est :

    if faut mettre le flag tm_isdst à -1, comme dit dans le man mktime, même si c'est pas très clair (je suis tombé sur ce post en ayant le même problème). passer ce flag en valeur negative permet de considère que la date est rentré au bon format.

    Comme quoi, si tu ne trouve pas la solution après avoir lu 10 fois le man, lis-le une 11 fois.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    192
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 192
    Par défaut regarder du côté de _mkgmtime()
    j'étais tombé sur ce thread l'autre jour pour un problème du même type.

    Pour ma part utiliser _mkgmtime() en lieu et place de mktime()
    a complètement résolu le problème que j'avais.

  11. #11
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par temoanatini Voir le message
    Pour ma part utiliser _mkgmtime() en lieu et place de mktime()
    a complètement résolu le problème que j'avais.
    et pour ceux n'ayant pas accès à cette fonction :


    http://c.developpez.com/sources/?pag...ktime_from_gmt

  12. #12
    Membre Expert Avatar de scheu
    Inscrit en
    Juin 2007
    Messages
    1 506
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 1 506
    Par défaut
    Citation Envoyé par ITCsoft54 Voir le message
    if faut mettre le flag tm_isdst à -1
    Je confirme, j'ai récemment rencontré le même problème
    Mettre flag tm_isdst de la structure tm à -1 désactive la prise en compte de l'heure d'été/hiver et du coup élimine le risque que la fonction mktime te renvoie 1h de plus ou de moins

    Un petit programme à tester pour bien comprendre :
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
     
     
    int main(int argc, char *argv[])
    {
            struct tm tm;
            time_t t;
     
            printf("Testing 2010-02-21 08:00:00 (winter time)\n");
     
            memset(&t, 0, sizeof(t));
            tm.tm_year = 110; tm.tm_mon = 2; tm.tm_mday = 21; tm.tm_hour = 8; tm.tm_min = 0; tm.tm_sec = 0;
            tm.tm_isdst = 0;
            t = mktime(&tm);
            printf ("tm_isdst= 0 - time  : %s",ctime(&t));
            /* previous line should display "tm_isdst= 0 - time  : Sun Mar 21 08:00:00 2010" */
     
            memset(&t, 0, sizeof(t));
            tm.tm_year = 110; tm.tm_mon = 2; tm.tm_mday = 21; tm.tm_hour = 8; tm.tm_min = 0; tm.tm_sec = 0;
            tm.tm_isdst = -1;
            t = mktime(&tm);
            printf ("tm_isdst=-1 - time  : %s",ctime(&t));
            /* previous line should display "tm_isdst=-1 - time  : Sun Mar 21 08:00:00 2010" */
     
     
            printf("Testing 2010-04-21 08:00:00 (summer time)\n");
     
            memset(&t, 0, sizeof(t));
            tm.tm_year = 110; tm.tm_mon = 4; tm.tm_mday = 21; tm.tm_hour = 8; tm.tm_min = 0; tm.tm_sec = 0;
            tm.tm_isdst = 0;
            t = mktime(&tm);
            printf ("tm_isdst= 0 - time  : %s",ctime(&t));
            /* previous line should display "tm_isdst= 0 - time  : Fri May 21 09:00:00 2010" */
     
            memset(&t, 0, sizeof(t));
            tm.tm_year = 110; tm.tm_mon = 4; tm.tm_mday = 21; tm.tm_hour = 8; tm.tm_min = 0; tm.tm_sec = 0;
            tm.tm_isdst = -1;
            t = mktime(&tm);
            printf ("tm_isdst=-1 - time  : %s",ctime(&t));
            /* previous line should display "tm_isdst=-1 - time  : Fri May 21 08:00:00 2010" */
     
            return 0;
    }
    Si tu es sous Unix , une autre solution serait de positionner dans ton shell la variable TZ ("export TZ=Europe/Paris" par exemple), avant de lancer ton programme, ça évite de modifier ton code C surtout si ta fonction mktime est appelée un peu partout dans ton programme
    La théorie, c'est quand on sait tout mais que rien ne fonctionne.
    La pratique, c'est quand tout fonctionne mais que personne ne sait pourquoi.
    Ici, nous avons réuni théorie et pratique : Rien ne fonctionne ... et personne ne sait pourquoi !

    Réplication de base avec Postgresql : http://scheu.developpez.com/tutoriel.../log-shipping/

  13. #13
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par scheu Voir le message
    Si tu es sous Unix , une autre solution serait de positionner dans ton shell la variable TZ ("export TZ=Europe/Paris" par exemple), avant de lancer ton programme, ça évite de modifier ton code C surtout si ta fonction mktime est appelée un peu partout dans ton programme
    Sauf que cela le modifie pour tous les processus..

    D'où la solution de ma fonction citée en référence dans le post au dessus, où ceci est fait DANS la fonction, et donc uniquement touchant le programme en question..

  14. #14
    Membre Expert Avatar de scheu
    Inscrit en
    Juin 2007
    Messages
    1 506
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 1 506
    Par défaut
    Effectivement il peut y avoir des effets de bord ...

    Ou alors le positionner uniquement dans le shell qui lance ton programme C, plutôt qu'au niveau du compte Unix
    La théorie, c'est quand on sait tout mais que rien ne fonctionne.
    La pratique, c'est quand tout fonctionne mais que personne ne sait pourquoi.
    Ici, nous avons réuni théorie et pratique : Rien ne fonctionne ... et personne ne sait pourquoi !

    Réplication de base avec Postgresql : http://scheu.developpez.com/tutoriel.../log-shipping/

Discussions similaires

  1. Réponses: 1
    Dernier message: 14/02/2013, 17h29
  2. Utilisation de mktime
    Par D[r]eadLock dans le forum Télécharger
    Réponses: 0
    Dernier message: 30/11/2010, 16h15
  3. Réponses: 1
    Dernier message: 01/06/2010, 11h40
  4. Réponses: 11
    Dernier message: 24/07/2007, 15h14
  5. Réponses: 1
    Dernier message: 12/04/2005, 20h36

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