Jugando con el tiempo

Funciones de manejo de fechas y horas.

GLib proporciona una API completa para poder programar, utilizando fechas dentro de nuestras aplicaciones de forma sencilla. El objetivo fundamental es dar soporte a las fechas, cuya programación puede ser pesada sin estas funciones, aunque también se proporcionan algunos métodos para relacionar tiempos y fechas. Para ello, GLib dispone de la estructura GDate, la cual es la estructura que incorpora toda la información sobre las fechas y, además, una serie de funciones que interactúan con esa estructura.

Antes de empezar, han de aclararse unos conceptos sobre la expresión del tiempo, en cuanto al formato de las fechas se refiere. Hay dos formas de expresar las fechas: día-mes-año y formato Juliano; este último es simplemente el número de días que han transcurrido desde una fecha de referencia (en el caso de GLib, dicha fecha es el 1 de Enero del año 1).

Creación de una nueva fecha.

El primer paso para poder utilizar una fecha es crearla. Para crear una fecha se dispone de varias funciones, la primera, g_date_new, permite crear una estructura GDate sin ningún valor. Esta función resultará útil más adelante cuando se vea como ajustar la estructura GDate a una determinada fecha. Las dos siguientes permiten crear una fecha pero, al contrario que la anterior, que sólo crea la estructura, éstas añaden además la fecha: la función g_date_new_julian, que nos permite crear una fecha utilizando el formato juliano y, por último, g_date_new_dmy, a la que se le pasa un día, mes y año para crear el GDate.

GDate * g_date_new ( void );

GDate * g_date_new_julian (guint32 dia_juliano );

GDate * g_date_new_dmy (GDateDay dia , GDateMonth mes , GDateYear año );

En esta última función, es conveniente que se examinen los tipos de datos GDateDay, GDateMonth, GDateYear.

El tipo de datos GDateDay es un entero (entre 1 y 31) que representa el día del mes. La constante G_DATE_BAD_DAY representa un día inválido del mes.

El tipo GDateMonth es un tipo enumerado, por tanto se puede referir a él con un número del 1 al 12, refiriéndose a los meses de enero a diciembre o también con los elementos G_DATE_JANUARY, G_DATE_FEBRUARY, etc. La constante G_DATE_BAD_MONTH representa un mes inválido.

Y, por último, está el tipo GDateYear. Este tipo es, en realidad, un entero; por tanto, para representar el año, basta con poner el número del año deseado.

Midiendo intervalos de tiempo con GTimer.

Dentro del mundo de la programación, medir el tiempo entre dos instantes dentro del programa es una actividad bastante común. Por ejemplo, en programas que transfieren un archivo y miden la velocidad de transferencia o en programas de instalación, para mostrar por pantalla el tiempo de instalación usado. La medida del tiempo es tan necesaria como, a veces, dependiente de la plataforma para la que se desarrolle. Por eso, GLib provee la estructura GTimer y sus funciones asociadas, gracias a lo cual, se podrá calcular intervalos de tiempo con una resolución del orden de los microsegundos.

Descripción de las funciones para manejar GTimer.

La estructura GTimer es opaca para el programador. Todo lo necesario para gestionar GTimer se realiza con las funciones que se describen a continuación, lo que quiere decir que no se mostrará en el libro la estructura en detalle como se hizo en otras secciones, ya que ni el mismo programador la ve. Sólo se interactúa con ella a través de funciones, como ya se ha dicho.

Para empezar, lo primero que se ha de hacer, como en la gran mayoría de estructuras de GLib, es inicializar o crearla. Para este fin se dispone de la función g_timer_new. Esta función se encarga única y exclusivamente de inicializar la estructura GTimer.

GTimer * g_timer_new ( void );

Una vez inicializada la estructura GTimer, lo siguiente es ver qué se puede hacer con ella. Como se mencionó previamente, esta estructura está dedicada a medir intervalos de tiempo y se propuso el ejemplo de un programa en el cual se transfiere un archivo y mide el tiempo de transferencia. Si se abstrae el problema en sí y se fija la atención solamente en lo que tendría que hacer el programa para medir los tiempos, se llegará a la conclusión que se requiere una función que arranque el contador de tiempo para que, cuando empezase la transferencia, se marcase de alguna manera el tiempo en el que se empezó a transferir, y una función que pare el contador cuando el archivo acabe de transferirse. Y, por último, una función con la cual se pueda consultar el tiempo en un momento dado, una vez arrancado el contador. Pues todas esas funciones están implementadas en GTimer.

Para empezar, existe la función g_timer_start, que tiene la función de marcar el tiempo de inicio en el que se ha arrancado el contador. Luego está g_timer_stop que marca el momento final de la medida de tiempo. Y por último g_timer_elapsed, que tiene un carácter más complejo, pero que resulta sencillo de comprender. Esta función devuelve el número de segundos que hayan transcurrido y, si se desea más precisión el puntero a microsegundos devolverá el número de microsegundos. Ahora bien, si se ha iniciado el contador pero aún no se ha detenido con g_timer_stop, obtiene el tiempo transcurrido desde que se inició el contador. Si se ha llamado a g_timer_stop, obtiene el tiempo transcurrido entre el inicio del contador de tiempo y el momento en que fue detenido.

void g_timer_start ( GTimer * contador );

void g_timer_stop ( GTimer * contador );

gdouble g_timer_elapsed ( GTimer * contador , gulong * microsegundos );

Ahora, en un contexto un poco más avanzado, GTimer también dispone de una función que reinicia el contador: g_timer_reset. Esta función es equivalente a llamar a g_timer_start si el contador ya está activo, es decir, reinicia el contador de tiempo poniendo como instante inicial, el momento de la llamada a esta función. En el caso de estar parado, lo pone a cero.

GTimer * g_timer_reset ( GTimer * timer );

Y, por ultimo, y dado que la estructura GTimer es una estructura opaca al desarrollador, necesitamos una función que libere todos los recursos de memoria que haya requerido la estructura, es decir, una función que libere de memoria la estructura GTimer. Para ello está g_timer_destroy.

GTimer * g_timer_destroy ( GTimer * timer );

Como unas líneas de código valen más que mil palabras, aquí se propone un ejemplo que aclara dudas sobre el uso de estas funciones si las hubiere.

Ejemplo 6-4.1. Ejemplo de uso de GTimer

   1 /* ejemplo del uso de GTimer */
   2 #include <unistd.h> /* contiene la función sleep */
   3 #include <glib.h>
   4 
   5 int
   6 main ()
   7 {
   8         GTimer *timer1, *timer2;
   9         gdouble elapsed;
  10         gulong usec;
  11         
  12         timer1 = g_timer_new (); /* Llama implícitamente a g_timer_start() */
  13         timer2 = g_timer_new ();
  14         
  15         g_print ("Duermo 5 segundos...");
  16         sleep (5);
  17         g_print ("\n\n");
  18         
  19         g_print ("Paro el timer 1...\n");
  20         g_timer_stop (timer1);
  21         
  22         elapsed = g_timer_elapsed (timer1, &usec);
  23         g_print ("Tiempo transcurrido timer 1: %gs %luus\n", elapsed, usec);
  24         
  25         elapsed = g_timer_elapsed (timer2, &usec);
  26         g_print ("Tiempo transcurrido timer 2: %gs %luus\n\n", elapsed, usec);
  27         
  28         g_print ("Duermo 1 segundo más...\n");
  29         sleep (1);
  30         
  31         elapsed = g_timer_elapsed (timer1, &usec);
  32         g_print ("Tiempo transcurrido timer 1 (igual que antes): \
  33                   %gs %luus\n", elapsed, usec);
  34         elapsed = g_timer_elapsed (timer2, &usec);
  35         g_print ("Tiempo transcurrido timer 2 (un segundo más): \
  36                   %gs %luus\n\n", elapsed, usec);
  37         
  38         g_print ("Reseteo el timer 1 (que esta parado).\n");
  39         g_timer_reset (timer1);
  40         g_print ("Reseteo el timer 2 (que esta activo).\n");
  41         g_timer_reset (timer2);
  42         
  43         g_print ("Duermo otro segundo más...\n");
  44         sleep (1);
  45         
  46         elapsed = g_timer_elapsed (timer1, &usec);
  47         g_print ("Tiempo transcurrido timer 1 \
  48                   (0, no se ha llamado a g_timer_start()): \
  49                   %gs %luus\n", elapsed, usec);
  50         
  51         elapsed = g_timer_elapsed (timer2, &usec);
  52         g_print ("Tiempo transcurrido timer 2 (1 segundo): \
  53                   %gs %luus\n\n", elapsed, usec);
  54         
  55         g_print ("Llamo a g_timer_start () con timer 1.\n");
  56         g_timer_start (timer1);
  57         
  58         g_print ("Y vuelvo a dormir, 2 segundos...\n");
  59         sleep (2);
  60         
  61         elapsed = g_timer_elapsed (timer1, &usec);
  62         g_print ("Tiempo transcurrido timer 1 (2 segundos): \
  63                   %gs %luus\n", elapsed, usec);
  64         elapsed = g_timer_elapsed (timer2, &usec);
  65         g_print ("Tiempo transcurrido timer 2 (3 segundos): \
  66                   %gs %luus\n\n", elapsed, usec);
  67         
  68         g_timer_destroy (timer2);
  69         g_timer_destroy (timer1);
  70         
  71         return 0;
  72 }


Volver a: GLib

Documentacion/Desarrollo/Glib/JugandoConElTiempo (última edición 2008-12-04 08:49:12 efectuada por localhost)