Ce cours est visible gratuitement en ligne.

Got it!
time.h et ses fonctions
Last updated on Tuesday, November 19, 2013
  • 2 heures
  • Facile

Introduction du cours

Bonjour à tous !

Vous venez de terminer la lecture des deux premiers chapitres du cours officiel sur le C ? Mais vous avez peut-être remarqué que la gestion du temps manque à l'appel.

Effectivement, la gestion du temps (que ce soit créer une attente ou afficher la date) ne fait pas partie du tutoriel officiel du C de M@teo21. Et c'est ce que je vais vous apprendre tout au long de ce cours.

La gestion du temps en C/C++ passe par la bibliothèque time.h, renommée en ctime en C++. Donc pour suivre le cours, vous devrez utiliser la directive de préprocesseur correspondant au langage dans lequel vous compilez :

#include <time.h>
#include <ctime>

Grâce à cette directive de préprocesseur, vous serez apte à utiliser l'intégralité des fonctions présentes dans la bibliothèque time.h.

Bonne lecture !

Obtenir une date et une heure

Dans cette partie nous allons voir :

  • comment obtenir la date et l'heure actuelle ;

  • comment situer son programme dans le temps (et ainsi créer un chronomètre, par exemple).

struct tm : Structure du temps

Pour manipuler les dates et les heures, il nous faut de quoi stocker le temps de manière compréhensible, c'est-à-dire qu'au lieu d'une seule variable contenant des secondes (on se retrouverait avec des modulos partout), nous aurons une structure contenant un instant mais utilisant les différentes unités et informations que l'on emploie (année, mois, jour du mois, jour de la semaine, jour de l'année, heure, minute, seconde et si nous sommes en heure d'été ou d'hiver).

struct tm répond à ce besoin. Il s'agit d'une structure contenant les variables suivantes.

Variable

Représente

Rang

tm_year

Le nombre d'années depuis 1900.

0 - ?

tm_mon

Mois écoulés depuis janvier (n° du mois-1).

0 - 11

tm_yday

Nombre de jours écoulés depuis le 1er janvier (n° jour-1).

0 - 365

tm_mday

Numéro du jour du mois.

1 - 31

tm_wday

Nombre de jours écoulés depuis dimanche (et non lundi).

0 - 6

tm_hour

Nombre d'heures écoulées depuis minuit.

0 - 23

tm_min

Nombre de minutes écoulées depuis le dernier changement d'heure.

0 - 59

tm_sec

Nombre de secondes écoulées depuis le dernier changement de minute.

0 - 60*

tm_isdst

-1 si l'information est indisponible ;
0 si c'est l'heure d'hiver ;
+1 si c'est l'heure d'été.

-

? : Dépend de la façon dont la date est gérée par votre système d'exploitation.
* : Certains systèmes nécessitent une marge pour éviter des bugs. Néanmoins, retenez 0 - 59. Cette marge n'a pas vraiment d'importance.

Cette structure correspond donc à la représentation d'un instant avec de nombreuses informations simples à exploiter ! Nous n'allons pas encore la remplir automatiquement suivant l'heure interne de votre ordinateur, mais je vous propose un code d'exemple pour comprendre son utilisation (pas très propre mais c'est pour l'exemple).

Exemple

#include <stdio.h>
#include <time.h>

int main(void)
{
    struct tm instant;
    int remplir;

    printf("Entrez le mois : ");
    scanf("%d", &remplir);
    instant.tm_mon = remplir-1;

    printf("Entrez le jour : ");
    scanf("%d", &remplir);
    instant.tm_mday = remplir-1;

    printf("Entrez l'heure : ");
    scanf("%d", &remplir);
    instant.tm_hour = remplir;

    printf("Entrez la minute : ");
    scanf("%d", &remplir);
    instant.tm_min = remplir;

    printf("Entrez la seconde : ");
    scanf("%d", &remplir);
    instant.tm_sec = remplir;

    printf("%d/%d ; %d:%d:%d", instant.tm_mday+1, instant.tm_mon+1, instant.tm_hour, instant.tm_min, instant.tm_sec);
    return 0;
}

Pour les directives de préprocesseur, on inclut bien sûr stdio.h pour les fonctions printf() et scanf() et time.h pour notre struct tm. stdlib.h n'est pas nécessaire dans notre cas.

Dans la fonction int main(void) (void signifie que la fonction ne prend rien), on a la déclaration de la structure instant de type struct tm et la variable « remplir » qui nous servira à supprimer un décalage par la suite. Puis on demande à l'utilisateur d'entrer des valeurs qui seront conservées dans les variables appropriées en passant par « remplir ». Grâce à « remplir », on supprime le décalage présent pour le mois et le jour. Pour les heures, minutes et secondes, ce n'est pas la peine. Pour remplir la structure, on remplit chaque variable en la précédant du nom de la structure et d'un point. Les structures vous sont expliquées dans le cours officiel.

Au sein de la fonction printf(), on a une mise en forme des valeurs que l'on a remplies. Remarquez que les variables tm_mday et tm_mon ne sont pas affichées telles qu'elles sont mais avec une incrémentation afin d'obtenir les vrais numéros du mois et du jour. En fait, cela sert à remettre tout ça dans les bonnes valeurs. Ces problèmes de décalages peuvent être assez déroutants, mais on comprend très vite grâce au tableau situé au début de cette partie.

Voici ce que ça peut donner :

Entrez le mois : 11
Entrez le jour : 10
Entrez l'heure : 0
Entrez la minute : 0
Entrez la seconde : 0
10/11 ; 0:0:0

Exercice

Ajoutez les années à mon code. Attention, il y a un piège !

clock() : Situer son programme dans le temps

clock() est un bidule assez intéressant. Il permet de situer son programme dans le temps. Voici son prototype :

clock_t clock (void);

Cette fonction ne prend donc aucun paramètre et renvoie un nombre sous un nouveau type : le clock_t. Le type clock_t permet d'exprimer un nombre de clock ticks. Utilisez donc ce type lorsque vous souhaitez utiliser des clock ticks (comme le type size_t fait référence à une taille).

Le clock tick (ou battement pour les puristes du français) est une unité de mesure du temps interne de votre ordinateur. Qu'est-ce que ça représente par rapport à la seconde ? Eh bien…
Vous l'avez deviné : ça dépend !
En fait, cette valeur dépend de votre système d'exploitation et de votre processeur. time.h possède une macro permettant savoir combien de clock ticks par seconde votre ordinateur gère. Il s'agit de la macro CLOCKS_PER_SEC.

Bon, assez parlé, testons clock().

#include <stdio.h>
#include <time.h>

int main(void)
{
    printf("%f\n", (double) clock());
    return 0;
}

Ce code est un programme tout bête qui affiche la valeur retournée par clock(). Remarquez le (double) avant l'appel de la fonction. Il permet de transformer les clock_t renvoyés en double afin d'éviter un beau warning. On appelle cette action le cast (un cast en (int) marche, mais néanmoins il arrive que ce type contienne un nombre décimal, alors on utilise %f avec un cast(double), mais attention, ça ne marche pas dans tous les cas).

Qu'affiche-t-il ?

0

Aïe. Quelque chose ne va pas dans ton code.
Laisse-moi deviner. Comme clock() est appelée dès le début, elle renvoie le début du programme, soit 0 clock tick ?

Exactement ! Il va donc falloir mettre une attente avant l'appel de clock().

#include <stdio.h>
#include <time.h>

int main(void)
{
    getchar();

    printf("%f\n", (double) clock());
    return 0;
}

Un getchar() vous demandera d'appuyer sur la touche Entrée avant de continuer et d'afficher la valeur renvoyée par clock().

C'est bien beau, mais tu as dit que cette fonction était intéressante.
Or, ça ne sert à rien.

Bien au contraire ! Réfléchissez bien. Cela permet de faire un chronomètre par exemple ! Voyez cette nouvelle version du Plus ou Moins !

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int mystere, nombreentre;
    clock_t temps;

    srand(time(NULL));
    mystere=rand()%100+1;

    do{
        puts("Quel est le nombre ? ");
        scanf("%d", &nombreentre);

        if(nombreentre>mystere)
            puts("C'est moins !\n");
        if(nombreentre<mystere)
            puts("C'est plus !\n");
        if(nombreentre==mystere){
            temps=clock();
            printf("Bravo !\nTu as mis %f secondes a trouver le nombre.\n", (double) temps/CLOCKS_PER_SEC);
        }
    }while(nombreentre!=mystere);

    return 0;
}

C'est le même logiciel (je l'ai un peu simplifié mais c'est le même principe) sauf que l'on a ici une variable temps de type clock_t et lorsque le nombre est trouvé, on lui donne la bonne valeur via la fonction clock(). Après cela, on affiche les résultats grâce au fameux %f et une division temps/CLOCKS_PER_SEC sans oublier le cast (double) avant pour éviter un warning. Grâce à cette division, on obtient des secondes et non des clock ticks.

Quel est le nombre ?
61
Bravo !
Tu as mis 13.156000 secondes a trouver le nombre.

Exercice

On peut faire un chronomètre, mais aussi une attente ! Créez une fonction permettant de faire une attente et qui aura ce prototype :

void attendre(float temps);

Le temps sera bien sûr en secondes (et pas en siècles…).

C'est parti !

Correction
Il fallait utiliser une boucle vide se répétant tant que clock() ne renvoie pas une valeur que l'on a prédite à l'avance via un petit calcul. J'ai réalisé, en plus de cette fonction, un petit programme pour tester.

#include <stdio.h>
#include <time.h>

void attendre(float temps);

int main(void)
{
    int compteur;

    for(compteur=10;compteur>0;compteur--){
        printf("%d...\n", compteur);

        attendre(1);
    }

    puts("BONNE ANNEE !!!\n");

    return 0;
}

void attendre(float temps)
{
    clock_t arrivee=clock()+(temps*CLOCKS_PER_SEC); // On calcule le moment où l'attente devra s'arrêter

    while(clock()<arrivee);
}

Pour calculer le moment où l'attente s'arrête, on prend le moment dans lequel on se trouve (le début de l'attente) puis on y ajoute le temps d'attente en le transformant en clock ticks (d'où la multiplication par CLOCKS_PER_SEC).

Par contre, cette attente n'est pas aussi géniale que l'on pourrait le croire. En effet, elle consomme beaucoup de CPU. Il existe deux fonctions plus propres et moins gourmandes pour faire une attente : sleep() et Sleep() (la majuscule fait toute la différence).

sleep() est dans le header unistd.h (Linux et Mac uniquement) et Sleep() dans windows.h (vous savez pour quel système d'exploitation !). De plus elles ne prennent pas la même unité : Sleep() attend des millisecondes d'après sa page sur la MSDN et sleep() des secondes. Voici donc un code préprocesseur vous permettant d'obtenir une fonction attendre propre et portable sous forme de macro :

#if defined (WIN32) || defined (WIN64)
#include <windows.h>
#define ATTENDRE(temps) Sleep(temps*1000)
#else
#include <unistd.h>
#define ATTENDRE(temps) sleep(temps)
#endif

time() : Obtenir la date et l'heure

Attention, nous allons enfin voir comment remplir une struct tm avec l'heure interne de votre ordinateur. Mais nous avons besoin de passer par deux fonctions pour ce faire. La première est time(). Elle est souvent utilisée dans la génération de nombres pseudo-aléatoires (voyez le Plus ou Moins). Mais que fait-elle ? Voyons son prototype…

time_t time(time_t *variable);

Un nouveau type ! time_t est un type de variable qui sert à indiquer un nombre de secondes.

Bon ! En fait, time() a un fonctionnement assez bizarre : faire variable=time(NULL) revient à faire time(&variable) (n'oubliez pas le &, sinon, warning). time() va mettre la valeur à renvoyer directement dans la variable dans les deux cas (d'où l'utilisation du NULL dans le premier cas, vu qu'il n'y a aucune variable à remplir en paramètre).

Et ce qu'elle renvoie, ça correspond à quoi ?

La valeur renvoyée correspond au nombre de secondes écoulées depuis le premier janvier 1970. Non, cette date ne correspond à rien d'autre que le début du calendrier sur la plupart des systèmes d'exploitation.

Juste comme ça, pourquoi l'utilise-t-on pour générer des nombres pseudo-aléatoires ?

srand() demande un nombre pour l'initialiser car si on lui donne le même nombre, la fonction génèrera la même suite de nombres. Alors on utilise le temps car il est très rare de lancer deux fois le même programme dans la même seconde.

Voyons un exemple tout bête de la fonction time() :

#include <stdio.h>
#include <time.h>

int main(void)
{
    printf("Il s'est ecoule %f secondes depuis le 1er janvier 1970.\n", (double) time(NULL));

    return 0;
}
Il s'est ecoule 1298819112 secondes depuis le 1er janvier 1970.

Spécial quizz : devinez à quel moment j'ai lancé mon programme sans utiliser les fonctions que nous verrons par la suite !

localtime() : Utiliser ce qui est renvoyé par time() pour remplir une struct tm

time(), c'est bien, mais on ne peut pas en faire grand chose. localtime() va nous permettre d'utiliser time() pour remplir une struct tm. Voici son prototype :

struct tm* localtime (const time_t *secondes);

Elle prend un nombre de secondes pour renvoyer un pointeur vers une struct tm. Et devinez comment on fait pour remplir une struct tm avec l'heure actuelle ? C'est simple ! On récupère d'abord le temps actuel grâce à time() puis on remplit notre struct tmvialocaltime().

La valeur renvoyée est un pointeur vers une zone mémoire allouée statiquement et partagée entre les fonctions gmtime(), localtime() et ctime(). Vous pouvez donc utiliser des pointeurs pour ne pas avoir à copier la valeur de cette zone mémoire. Attention cependant à utiliser cela correctement car les précédentes valeurs de la zone mémoire seront écrasées lors des prochains appels de ces fonctions.

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t secondes;
    struct tm instant;

    time(&secondes);
    instant=*localtime(&secondes);

    printf("%d/%d ; %d:%d:%d\n", instant.tm_mday+1, instant.tm_mon+1, instant.tm_hour, instant.tm_min, instant.tm_sec);
    return 0;
}

C'est le même code que lorsque je vous ai appris à remplir une struct tm sauf que, cette fois-ci, les fonctions le font pour nous. Remarquez que pour remplir « instant », j'utilise un pointeur. Si je ne mets pas cet astérisque (*), on renvoie un pointeur dans une struct tm, ce qui provoque une erreur lors de la compilation.

28/2 ; 16:32:28

gmtime() : Obtenir l'heure GMT

Lire l'article GMT sur Wikipédia

L'heure GMT, c'est l'heure qu'il est en Grande Bretagne, chez nos amis les anglais. Or, en France, au Québec ou en Australie ce n'est pas la même heure. Mais en utilisant gmtime(), on peut récupérer l'heure GMT.

struct tm* gmtime (const time_t *temps);

Cette fonction prend en paramètre le nombre de secondes depuis le 1er janvier 1970 dans votre fuseau horaire (pas besoin de conversion) et renvoie l’adresse mémoire de time.h destinée aux struct tm (reportez-vous à la partie sur localtime()) après l'avoir remplie avec l'heure GMT. Par exemple en France, ce sera une heure avant puisque la France se situe dans le fuseau horaire +1.

Son utilité ? Imaginez que vous habitiez à Sydney en Australie et que vous souhaitiez prendre l'avion pour New York aux États-Unis. Vous savez combien de temps dure le trajet mais vous voulez arriver dans une fourchette d'heures bien précise (disons entre 13h et 15h, heure de New York). Vous connaissez la durée du trajet, oui mais pas l'heure qu'il est là-bas. gmtime() vous permettra de la trouver avec des calculs très simples.

Voici la représentation du monde avec les différents fuseaux horaires.

Représentation du monde avec les différents fuseaux horairesReprésentation du monde avec les différents fuseaux horaires.
Image tirée de Wikipédia, œuvre placée dans le domaine public.

Sydney se trouve donc dans un fuseau horaire GST (GMT+10) et New York dans un fuseau horaire EST (GMT-5). Cela signifie que lorsqu'il est minuit à Greenwich — ville où a été placé le méridien d'origine et donc le fuseau horaire UDC (celui correspondant à l'heure GMT) —, il est 10 heures à Sydney et 19h à New York.

#define SYD 10
#define NYC -5

Un moyen simple est de créer des macros correspondant aux fuseaux horaires (certains fuseaux horaires ont des noms civils et militaires mais pour des raisons de simplicité, j'ai mis les noms des villes Sydney et New York City) correspondant au décalage horaire par rapport à GMT.

Tableau répertoriant les noms civils et militaires des fuseaux horaires

#include <stdio.h>
#include <time.h>
#define SYD 10
#define NYC -5

int main(void)
{
    time_t temps;
    struct tm date;

    time(&temps);
    date=*gmtime(&temps);

    printf("GMT: %d:%d\n", date.tm_hour, date.tm_min);
    printf("Sydney: %d:%d\n", (date.tm_hour+SYD+24)%24, date.tm_min);
    printf("New-York: %d:%d\n", (date.tm_hour+NYC+24)%24, date.tm_min);

    return 0;
}

Après avoir placé nos macros et initialisé nos variables, on récupère l'heure GMT actuelle viatime() et gmtime(). Ensuite, on place des printf() qui doivent nous indiquer l'heure GMT, l'heure de Sydney et l'heure de New York. Pour la calculer, on fait le calcul (heure+décalage+24)%24. Le modulo est nécessaire car si on ne le met pas, on pourrait se retrouver avec des heures comme 26:30. Et je n'aimerais pas créer de faille spatio-temporelle. De même pour le +24 avant le modulo. Si avec la soustraction de l'heure pour le fuseau horaire de New York on obtient une heure négative, il va falloir la transformer en un nombre positif entre 0 et 24. Pour ce faire, on ajoute tout simplement 24. Le modulo supprimera les heures en trop s'il y en a.

GMT: 17:1
Sydney: 3:1
New-York: 12:1

Entre nous, je crois que c'est fichu pour aller à New York aujourd'hui.

En tout cas, on en a enfin fini avec les différentes manières d'obtenir des informations relatives au temps. La partie 2 porte sur quelques manipulations et calculs réalisables avec les informations obtenues.

Effectuer des manipulations avec les informations obtenues

Vous savez maintenant obtenir un moment précis et situer votre programme dans le temps. Maintenant, nous allons utiliser les informations obtenues pour effectuer quelques manipulations. Seules deux fonctions seront vues, en fait :

  • difftime() pour trouver l'intervalle entre deux moments ;

  • mktime() pour compléter une struct tm à partir de seulement 3 variables et/ou exécuter le procédé inverse de localtime().

difftime() : Faire la différence entre deux instants

Ici, nous allons apprendre à faire une différence entre deux moments. Imaginez que vous souhaitiez battre le record du monde du temps d'enfermement dans un carton (oui ; je sais, c'est pourri). N'ayant pas de montre et dormant fréquemment, vous ne savez pas combien de temps vous avez passé dans votre boîte. Mais imaginez qu'à côté vous ayez un ordinateur ayant enregistré le moment où vous êtres entré et celui où vous êtes sorti. Eh bien difftime() fera automatiquement la différence entre ces deux moments ! Allez, lisez cette partie et tentez le record !

double difftime (time_t arrivee, time_t depart);

Vous l'aurez remarqué, on fait la différence à partir de deux time_t, soit deux nombres représentant le nombre de secondes écoulées depuis le 1er janvier 1970. Voyons voir ça.

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t depart, arrivee;
    time(&depart);

    puts("Tu peux maintenant aller faire autre chose...\n");
    getchar();

    time(&arrivee);
    printf("Tu t'es absente pendant %f secondes.", difftime(arrivee, depart));

    return 0;
}

Voilà, vous pouvez rentrer dans votre carton. Donc on initialise deux variables qui stockeront le départ et l'arrivée et on donne la bonne valeur à « départ ». Un getchar() sert à faire une attente jusqu'à ce que l'utilisateur appuie sur Entrée, et on donne la bonne valeur à « arrivee ». Puis viennent les résultats où on affiche ce que renvoie difftime(), soit le temps qui s'est écoulé entre le départ et l'arrivée. Il y a des avantages par rapport à clock(), mais pour de petites durées, il vaut mieux un bon clock() car vous obtiendrez des résultats plus précis en fonction du nombre de clock ticks par seconde.

Tu peux maintenant aller faire autre chose...


Tu t'es absente pendant 411.000000 secondes.

mktime() : Compléter une struct tm

Il arrivera souvent que vous remplissiez une struct tm mais à moitié. Et tout à coup, vous avez besoin d'une valeur que vous n'avez pas remplie. Comment la calculer ? mktime() va faire tout le boulot à votre place.

time_t mktime (struct tm *structure);

Cette fonction prend en paramètre une struct tm et renvoie la valeur time_t correspondante à celle-ci, soit le procédé inverse de localtime(). Mais elle ne sert pas qu'à ça. Elle sert en effet à remplir une struct tm incomplète à partir de ces 3 valeurs :

  • tm_year ;

  • tm_mon ;

  • tm_mday.

Toutes les autres valeurs mises à part « tm_hour », « tm_min » et « tm_sec » seront calculées à partir des 3 variables nécessaires. Cette fonction permet notamment de savoir quel jour de la semaine on est à partir du jour du mois, ou alors de connaître quel jour on sera dans x jours. Je pense que l'on peut trouver pas mal d'exemples, alors on va faire tout simple : savoir quel jour de l'année on est à partir d'une date précise !

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t temps;
    struct tm date;
    int remplir;

    // On demande à l'utilisateur de remplir les valeurs demandées.
    // Ne pas oublier d'additionner ou de soustraire les bonnes valeurs pour éviter les décalages.
    puts("Annee ? ");
    scanf("%d", &remplir);
    date.tm_year=remplir-1900;

    puts("Mois ? ");
    scanf("%d", &remplir);
    date.tm_mon=remplir-1;

    puts("Jour ? ");
    scanf("%d", &remplir);
    date.tm_mday=remplir;

    // On s'assure que l'instant est bien placé à minuit.
    date.tm_hour=0;
    date.tm_min=0;
    date.tm_sec=0;

    temps=mktime(&date);

    printf("C'est le %deme jour de l'annee !\nEt minuit est la %deme seconde depuis le 1er janvier 1970.\n", date.tm_yday, (int) temps);

    return 0;
}

On demande donc à l'utilisateur de remplir les champs « année », « mois » et « jour du mois » pour remplir les autres cases de la structure. Remarquez que j'ai mis les variables de l'heure, minutes et secondes à 0 pour se positionner sur minuit. Ensuite, après mktime(), on affiche « date.tm_yday » que mktime() a calculée, et petit bonus, la valeur renvoyée par mktime() qui correspond au nombre de secondes écoulées entre le 1er janvier 1970 à minuit et cette date.

Annee ?
1999
Mois ?
11
Jour ?
10
C'est le 312eme jour de l'annee !
Et minuit est la 942184800eme seconde depuis le 1er janvier 1970.

C'est loin d'être le seul exemple. Soyez créatif, il y a pas mal de possibilités !

Afficher l'heure obtenue

Cette troisième partie n'est pas la plus importante. Elle est cependant intéressante car elle va vous permettre d'écrire les moments obtenus dans vos programmes.

Un coup de printf() ne suffit-il pas ?

En fait, on va apprendre à placer l'heure écrite dans un format bien précis et directement dans une chaîne de caractères.

asctime() : Transformer une struct tm en char[]

Ce titre vous semble délirant, et pourtant c'est entièrement vrai : asctime() vous permet de transformer une struct tm en char[], c'est à dire mettre en forme le contenu de la struct tm et stocker le résultat dans une chaîne de caractères. Voici la syntaxe de cette fonction.

À l'image de la zone mémoire dédiée aux struct tm (reportez-vous à la partie sur localtime()), la valeur renvoyée par asctime() est un pointeur vers une zone mémoire de 26 caractères partagée entre asctime() et ctime().

char* asctime (const struct tm* instant);

Cette fonction prend donc un pointeur vers une struct tm en paramètre et retourne une chaîne (terminée par un retour à la ligne et un caractère 0) de caractères. La mise en forme obtenue est la suivante :

Jjj Mmm jm hh:mm:ss aaaa.

Dans l'ordre :

  • tm_wday, le jour de la semaine est exprimé en 3 lettres dans son nom anglais (ex : Lundi → Mon) ;

  • tm_mon, le nom du mois exprimé en 3 lettres dans son nom anglais (ex : Juin → Jun) ;

  • tm_mday, le jour du mois ;

  • tm_hour, l'heure ;

  • tm_min, les minutes ;

  • tm_sec, les secondes ;

  • tm_year, l'année.

Voyons voir ça !

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t temps;
    struct tm date;

    time(&temps);
    date=*localtime(&temps);

    printf("%s\n", asctime(&date));

    return 0;
}

Donc après avoir donné la bonne valeur à temps, on remplit date vialocaltime() et on utilise dans printf() la fonction asctime() en lui envoyant notre structure date.

On obtient la date et l'heure écrite dans le format que j'ai indiqué plus haut.

Sun Feb 27 21:39:40 2011

Exercice

Avec la fonction (ou la macro, comme vous préférez) attendre, créez une horloge ! Afin d'être la plus précise possible, votre horloge devra comporter une phase de synchronisation, boucle vide qui se répète tant que l'on n'est pas sûr que l'on est tout au début de la seconde.

ctime() : Transformer un time_t en char[]

char* ctime (const time_t *temps);

ctime() est une version raccourcie de asctime(). Au lieu de lui donner une struct tm, on lui donne directement un time_t, ce qui fait gagner du temps. Pour un exemple plus concret :

// Ces deux instructions donnent le même résultat.
asctime(localtime(&temps));
ctime(&temps);

La valeur renvoyée est un pointeur vers une zone mémoire qui est également utilisée par asctime(). Ces deux fonctions écraseront donc la chaîne contenue dans cet espace mémoire (à l'image des fonctions utilisant les struct tm).

#include <stdio.h>
#include <time.h>

int main(void)
{
    time_t temps;

    time(&temps);

    printf("%s\n", ctime(&temps));

    return 0;
}

Tout est du déjà vu, donc pas besoin de s'acharner là-dessus.

strftime() : Créer son propre format

Là ce sera plus dur : Nous allons toujours mettre en forme notre structure dans une chaîne de caractères, mais cette fois, nous allons créer notre propre format. En gros nous allons « créer » notre propre asctime().

size_t strftime (char *variable, size_t taillemax, const char *format, const struct tm *date);

C'est du lourd ! En fait, cette fonction est comme un printf(). Ses paramètres sont :

  • la chaîne qui contiendra la mise en forme ;

  • la longueur maximale de la chaîne ;

  • la mise en forme ;

  • un pointeur vers la structure à utiliser.

Qu'est-ce qu'elle retourne ? La longueur de la mise en forme si elle ne dépasse pas la longueur maximale autorisée. Si la chaîne mise en forme dépasse la limite que vous autorisez, la fonction retourne 0.

Donc la variable sera contenue dans une chaîne, il serait déjà bien d'en allouer une. 48 caractères suffiront, à moins que vous ne souhaitiez mettre un roman en tant que mise en forme. Après, à l'image de printf(), les « % » servent à afficher des valeurs. Voici un tableau pour vous donner une petite idée.

Symbole

Affichera

Exemple

%A

Nom du jour de la semaine.

Monday

%a

Nom du jour de la semaine en abrégé.

Mon

%B

Nom du mois.

January

%b

Nom du mois en abrégé.

Jan

%c

Représentation de la date et de l'heure classique.

02/27/11 22:05:45

%d

Numéro du jour dans le mois.

29

%H

Heure (0-24).

16

%I

Heure (0-12).

4

%j

Jour dans l'année.

342

%m

Numéro du mois.

12

%M

Minute.

51

%p

Affiche « AM » le matin et « PM » l'après-midi (utile après un « %I »).

PM

%S

Secondes.

12

%U

Numéro de la semaine dans l'année (dimanche = premier jour de la semaine).

53

%w

Numéro du jour dans la semaine (dimanche = 0).

2

%W

Numéro de la semaine dans l'année (lundi = premier jour de la semaine).

1

%x

Affiche la date (format mm/jj/aa).

03/20/05

%X

Affiche l'heure (format hh:mm:ss).

12:34:56

%Y

L'année.

2005

%y

Les deux derniers chiffres de l'année.

05

%Z

Nom du fuseau horaire.

Paris, Madrid

%%

Affiche un « % ».

%

Un gros morceau mais qui vous permettra un truc assez custom. Vous pourrez afficher le contenu de la chaîne obtenue avec un puts() :

puts(format);

Allez, voici une horloge pour servir d'exemple :

#include <stdio.h>
#include <time.h>

int main(void)
{
    char format[128];
    time_t temps;
    struct tm date;

    // On récupère la date et l'heure actuelles.
    time(&temps);
    date=*localtime(&temps);

    // On remplit la chaîne avec le format choisi, puis on l'affiche.
    strftime(format, 128, "%a %x\n%X %Z\n", &date);
    puts(format);

    return 0;
}

On stocke donc la mise en forme dans la chaîne « format » en accordant une longueur maximale de 128 caractères, puis l'écriture du format et l'adresse de « date » d'où seront tirées les informations.

Sun 02/27/11
22:24:32 Paris, Madrid

Grâce à cette fonction, vous serez capable de mettre en forme vos dates avec une bonne liberté !

Vous savez maintenant comment gérer le temps dans vos programmes ! De nouvelles aventures vous attendent ! Datez vos sauvegardes et vos meilleurs scores ! Placez un chronomètre dans vos programmes pour forcer le joueur à se creuser les méninges pour trouver la solution à vos jeux ! Battez le record du plus long enfermement dans un carton ou faites un voyage Sydney-New York sans aucun problème ! Le temps n'a plus de secret pour vous !

Liens utilisés pour la rédaction du tutoriel :

How courses work

  • 1

    You have now access to the course contents and exercises.

  • 2

    You will advance in the course week by week. Each week, you will work on one part of the course.

  • !

    Exercises must be completed within one week. The completion deadline will be announced at the start of each new part in the course. You must complete the exercises to get your certificate of achievement.

  • 3

    At the end of the course, you will get an email with your results. You will also get a certificate of achievement if you are a

Example of certificate of achievement
Example of certificate of achievement