FuncoesDeTempoNoC

De MediaWiki do Campus São José
Ir para: navegação, pesquisa

Introdução

Em vários projetos de desenvolvimento surge a necessidade de representar data e hora. Por exemplo, um evento em uma agenda eletrônica deve ter associado a ele uma data e hora do momento em que este evento acontece. É natural que se pense ema representação na forma de uma struct:

struct data_hora {
  int ano,
      mes,
      dia,
      hora,
      minuto,
      segundo
};

Entretanto, a biblioteca glibc da GNU já apresenta uma série de definições e funções sobre o tempo. É importante conhecê-las pois facilitarão o desenvolvimento dos programs no sentido que permitirão rapidamente ler a hora e data do sistema, computar intervalos de tempo, entre outras possibilidades.

A struct tm e o tipo (inteiro) time_t que representa o tempo

A struct tm, conforme manual do linux possui a seguinte estrutura:

/* definida em time.h - NÃO é necessário redefinir no seu código*/
struct tm {
               int tm_sec;    /* segundos (0-60) */
               int tm_min;    /* minutos (0-59) */
               int tm_hour;   /* horas (0-23) */
               int tm_mday;   /* dia do mês (1-31) */
               int tm_mon;    /* mês (0-11) */
               int tm_year;   /* ano - 1900 */
               int tm_wday;   /* dia da semana (0-6, Domingo = 0) */
               int tm_yday;   /* dia do ano (0-365, 1 Jan = 0) */
               int tm_isdst;  /* flag de horário de verão (HV): 1-se é HV, 0-não é HV, -1 se não existe esta informação */
};

Esta estrutura permite representar a data/hora calendário que um ser humano (programador em C :-) consegue facilmente entender e utilizar.

Por questões de otimização esta não é a melhor forma de representar o tempo em um sistema computacional. Também não é apropriada para representar intervalos de tempo. Desta forma, a biblioteca apresenta a definição time_t que possui uma estrutura adequada para o sistema computacional operar. Na prática é um tipo inteiro que representa o número de segundos desde 1 de Janeiro de 1970.

Vamos um exemplo mostrando como capturar o tempo do sistema:

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

main()
{
  struct tm *minha_data;
  time_t data_hora;

  time(&data_hora); /* ler do sistema a data_hora em segundos desde 1 de janeiro de 1970 */

  printf ("data hora em segundos desde 1970: %ld\n", data_hora);

  minha_data = localtime(&data_hora); /* convert de data representada em time_t para data em struct tm */

  printf("Ano %d Mês %d Dia %d Hora %d Minuto %d\n", minha_data->tm_year,  minha_data->tm_mon,  minha_data->tm_mday,  minha_data->tm_hour,  minha_data->tm_min);
}

Note que tempo lido do sistema através da função time() está na forma de segundos desde 1970 (um valor inteiro). Este tempo é então convertido para uma struct tm que pode ser manipulado pelas granularidades ano, mês etc.

Comparando tempo de eventos

Suponha que para registrar eventos em uma agenda, foi decidido usar o time_t. A comparação se torna bastante simples. Vamos a um exemplo:

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

struct tipo_evento{
   int tipo_evento; /* 0 - reunião, 1-aula, 2-consulta médica */
   struct tm data;
};

main()
{
    struct tipo_evento evento1 = {0, {0,0,15,29,10,2018-1900}}; /* evento em 29/11/2018 15h */
    struct tipo_evento evento2 = {1, {0,0,15,23,10,2018-1900}}; /* evento em 23/11/2018 15h */

    time_t aux1,aux2;

    aux1=mktime(&evento1.data); /* converte uma data na forma struct tm para time_t */
    aux2=mktime(&evento2.data); /* converte uma data na forma struct tm para time_t */

    if (aux1>aux2) {
        printf("evento 1 mais recente que evento 2\n");
    } else {
        printf("evento 1 antecede ou está na mesma data do evento 2\n");
    }

    /* vamos mudar o mês do evento 1 para um valor anterior ao evento 2 */
    evento1.data.tm_mon = 9;
    aux1=mktime(&evento1.data); /* tem que converter de novo... */

    if (aux1>aux2) {
        printf("evento 1 mais recente que evento 2\n");
    } else {
        printf("evento 1 antecede ou está na mesma data do evento 2\n");
    }   
}

Fazendo entrada de dados de forma temporizada

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

/*
  código adaptado de:
  https://www.unix.com/programming/16678-how-get-timed-input-using-cin.html
*/

int ler_val(int tempo, int *valor)
{
   fd_set fdset;
   struct timeval timeout;
   int  rc;
   int  erro;

   timeout.tv_sec = tempo;   /* espera "tempo" segundos */
   timeout.tv_usec = 0;


   FD_ZERO(&fdset);

   FD_SET(0, &fdset);

   rc = select(1, &fdset, NULL, NULL, &timeout);
   if (rc == -1)  /* falha no select */
   {
       erro = -1;
   }
   else if (rc == 0)  /* tempo esgotado */
   {
       erro=-2;
   }
   else 
   {
      if (FD_ISSET(0, &fdset)) 
      {
         erro=0;
         scanf("%d", valor);
      }
   }
   return erro;
}

main()
{
  int x,y;

  if (ler_val(5,&x)==0)
     printf("valor lido para x = %d\n", x);
  else
     printf("esgotado o tempo para ler x\n");    
  if (ler_val(5,&y)==0)
     printf("valor lido para y = %d\n", y);
  else
     printf("esgotado o tempo para ler y\n");    
}

Referências

http://www.catb.org/esr/time-programming/#_good_programming_practice