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

SL & STL C++ Discussion :

Affichage std::chrono::time_point "hybride"


Sujet :

SL & STL C++

  1. #1
    Futur Membre du Club
    Affichage std::chrono::time_point "hybride"
    Bonjour à tous,

    Je fais appel à vos talents et votre maîtrise de ce merveilleux langage qu'est le C++ (en toute subjectivité...) pour vous soumettre un problème un poil sioux.
    Tout d'abord, je vous présente ce que j'ai défini :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    typedef std::chrono::duration<double> time_lenght
    typedef std::chrono::time_point<std::chrono::system_clock, time_lenght> time_date;


    Maintenant je vous explique la raison : je manipule des variables de ce type pour effectuer des opérations ("+", "-", comparaison, ...). Un exemple concret :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    time_date mon_depart_theorique;
    time_date mon_arrivee;
     
    time_lenght ma_femme_se_prepare;
    time_lenght mes_enfants_se_disputent;
     
    if (mon_depart_theorique + ma_femme_se_prepare + mes_enfants_se_disputent <= mon_arrivee) {
      cout << "Ouais,  j'assure grave!" << endl;
    }
    else {
      cout << "Et m... Encore à la bourre au boulot..." << endl;
    }


    Tout fonctionne de manière correcte. J'ai de plus besoin de garder cette précision dans mes calculs.
    Et puis j'ai eu l'idée farfelue de vouloir faire du log en affichant mes durées et mes dates.
    Pour les durées, aucun souci : cout << ma_femme_se_prepare.count() << endl; affiche une valeur correcte (même si l'on pourrait s'attendre à un débordement...).
    Pour une différence entre time_date, là aussi c'est tout bon (cout << (mon_arrivee - mon_depart_theorique).count()).
    Par contre, afficher juste la date ne peut s'effectuer en passant par std::chrono::system_clock::to_time_t(mon_arrivee).
    Je fus naïf car je pensais avoir défini un type time_point basé sur system_clock.
    Mais le compilateur ne l'entend pas de cette manière et c'est logique puisqu'il s'attend à trouver en argument de to_time_t du std::chrono::system_clock::time_point.
    La subtilité c'est que cette spécialisation du patron std::chrono::time_point est défini avec une duration exprimée en int alors que je suis avec du double dans le mien.

    J'ai donc deux questions pour tenter de résoudre le schmi... le schlllmi, le schmmmbli... enfin le truc quoi :

    1. Est-ce la bonne manière de manipuler des time_point et des durations en voulant conserver une précision à la décimale ?
    2. Y-a-t-il un moyen d'afficher mon type time_date avec des fonctions standards sans avoir à redéfinir toute la STL ?



    Merci d'avance!

  2. #2
    Membre régulier
    Bonjour,

    Tout d'abord, je ne suis pas sûr d'avoir bien compris le problème mais j'ai quand même quelques remarques:
    a) Pourquoi ne pas utiliser directement std::chrono::time_point ? Quel serait le problème ?
    b) Pour convertir des time_point il y a time_point_cast si vraiment on cherche à manipuler des time_point différents...
    c) std::chrono::system_clock::from_time_t() prend en paramètre un std::time_t (type hérité du standard du langage C et équivalent d'un time_point en C++) . Le compilateur a de quoi ne pas être content si on lui donne un time_point en paramètre!!!

    Ensuite pour essayer de répondre aux questions:
    1. Ce n'est pas en changeant le type de représentation de la durée que l'on va améliorer la précision de son horloge système.
    Dans tous les cas on peut s'attendre à ce que la résolution minimum de l'horloge système soit de 0.01s.
    Après je dirai qu'il faudrait faire confiance à std::chrono::system_clock::time_point pour représenter une date avec cette horloge.
    2. Pour afficher une date en C++ on est obligé de repasser par les fonctions héritées du C (<ctime>) et d'utiliser le type std::time_t.
    Et en attendant que std::put_time (C++11) soit implémentée par GCC :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
            #include <ctime>
            #include <chrono>
            #include <iostream>
            /* ... */
    	std::time_t mon_depart_theorique_t(std::chrono::system_clock::to_time_t(mon_depart_theorique));
    	char str_heure_depart[64] = {0};
    	if (!std::strftime(str_heure_depart, sizeof(str_heure_depart),  "%H:%M:%S", std::localtime(&mon_depart_theorique_t))) {
                // Erreur 
            }
            std::cout << date;

  3. #3
    Futur Membre du Club
    Autant pour moi!

    Il y a une erreur dans ma demande initiale. Cela n'est pas un from_time_t que je veux faire mais bel et bien un to_time_t ! :-)
    Je précise à nouveau la problématique : je veux un time_point à partir duquel je puisse ajouter des durées évaluées à partir de valeurs exprimées en double.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ma_duration duree_depuis_double (un_double); //ça marche
     
    mon_time_point toto += duree_depuis_un_double; // ça marche
     
    std::chrono::system_clock::to_time_t (toto); // ça marche plus

  4. #4
    Membre régulier
    Il suffit d'utiliser time_point_cast avec le type "Duration" défini dans system_clock (voir le lien vers la doc dans mon message précédant).
    Ci-dessous un exemple complet :
    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
    #include <iostream>
    #include <chrono>
    #include <ctime>
     
    using time_lenght = std::chrono::duration<double>;
    using time_date   = std::chrono::time_point<std::chrono::system_clock, time_lenght>;
     
    int main()
    {
            time_date mon_depart_theorique = std::chrono::system_clock::now();
            time_lenght temps_de_trajet = std::chrono::minutes(40);
            time_lenght marge = std::chrono::minutes(20);
            time_date mon_arrivee = mon_depart_theorique + temps_de_trajet + marge;
            time_lenght ma_femme_se_prepare(59.);
            time_lenght mes_enfants_se_disputent(1140.123);
            if(mon_depart_theorique + temps_de_trajet + ma_femme_se_prepare + mes_enfants_se_disputent <= mon_arrivee) { 
                    std::cout << "Ouais, j'assure grave!" << std::endl;
            }
            else { 
                    std::cout << "Et m... Encore à la bourre au boulot..." << std::endl;
            }
            std::time_t mon_arrivee_t = std::chrono::system_clock::to_time_t(
                                            std::chrono::time_point_cast<std::chrono::system_clock::duration>(mon_arrivee));
            char mon_arrivee_str[64] {0};
            std::strftime(mon_arrivee_str, sizeof(mon_arrivee_str), "%H:%M:%S", std::localtime(&mon_arrivee_t));
            std:: cout << mon_arrivee_str << std::endl;
            return 0;
    }

  5. #5
    Futur Membre du Club
    iNaKoll,

    Tu es un chef!! Merci, c'est le cast qu'il fallait.
    Après j'utilise simplement std::ctime pour le moment :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    std::time_t mon_depart = std::chrono::system_clock::to_time_t(
                                            std::chrono::time_point_cast<std::chrono::system_clock::duration>(mon_time_point_hybryde));
    std::cout << std::ctime(&mon_depart) << std::endl;


    C'est vraiment cool!!

    A+