viernes, 20 de mayo de 2016

Manipulación de Fechas y Horas en C# - Parte 1/5: La Estructura TimeSpan

Índice

1. Introducción
2. Palabras Clave
3. Estructura TimeSpan
4. Creación de Objetos TimeSpan
5. Creación de String a TimeSpan
5.1 Parse
5.2 TryParse
6. Ejemplos de Uso
6.1 Creación de objetos
6.2 Aritmética con objetos TimeSpan
7. Prueba de Rendimiento
8. Conclusiones
9. Literatura & Enlaces

1. Introducción

Con esta nueva serie de artículos C# se estudiará el uso y aplicación de los tipos de datos disponibles en Microsoft .NET Framework para la manipulación de fechas y horas. Una aplicación puede requerir tratar con fechas y horas para registrar datos de aplicación de usuario para operaciones definidas, registros de actividad de usuario, sincronización de procesos, entre otros que pueden corresponder con tareas particulares de un modelo de un dominio específico. Con estos artículos se pretende familiarizar y dar una amplia introducción al programador del lenguaje de programación C#. En primer lugar se presenta el uso de la estructura TimeSpan: útil para representar intervalos de tiempo; luego se estudiará DateTime para fechas y hora. Así mismo, DateTimeOffset será estudiada; y al final la clase Daylight para definir horarios de verano.


Esta primera parte presenta la estructura TimeSpan para la representación de intervalos de tiempo. Aquí se estudia varias de las funciones integrales de esta construcción de la BCL: propiedades, constructores, métodos. Además, el uso de operadores sobrecargados para la aritmética de intervalos: adición y sustracción. Al final, se enseña una demostración de rendimiento entre el uso de constructores y métodos para la instanciación de objetos TimeSpan.

2. Palabras Clave

  • BCL
  • Estructura
  • Fecha
  • Intervalo de tiempo
  • Rendimiento
  • Sobrecarga de operadores
  • Tiempo

3. Estructura TimeSpan

La estructura TimeSpan ("TimeSpan Structure", 2016) es usada para la representación de intervalos de tiempo. Posee funciones -constructores, propiedades, métodos- para la manipulación de intervalos de tiempo y su representación. El tiempo se representa a partir de la medianoche sin considerar la transición de horarios de verano (Albahari, 2012).

Continuando, los valores asociados a esta estructura tienen una precisión de 100 nanosegundos (ns), y puede almacenar la representación de hasta 10 millones de días. Estas cantidades pueden ser positivas o negativas (Albahari, 2012).

4. Creación de Objetos TimeSpan

TimeSpan cuenta con las siguientes firmas para la instanciación de un objeto:
Constructores de TimeSpan
Figura 1. Constructores de TimeSpan ("TimeSpan Structure", 2016).
En el caso de la última versión sobrecargada de estos constructores -TimeSpan(Int64)-, se especifica un valor de tipo de dato long: cada unidad representa un tic de 100 nanosegundos.

Por otro lado, un mecanismo mecanismo para la creación de objetos TimeSpan consiste en el uso de métodos con el prefijo From...:

public static TimeSpan FromDays(double);
public static TimeSpan FromHours(double);
public static TimeSpan FromMinutes(double);
public static TimeSpan FromSeconds(double);
public static TimeSpan FromMilliseconds(double);

Nótese que todos estos métodos son static.

5. Conversión de String a TimeSpan

TimeSpan cuenta con los métodos Parse y TryParse para la conversión de objetos String a TimeSpan.

5.1 Parse

El método Parse ("TimeSpan.Parse", 2016) cuenta con dos versiones sobrecargadas. Este método convierte la representación literal de un intervalo a un objeto TimeSpan.

Console.WriteLine(TimeSpan.Parse("00:03:30"));

5.2 TryParse

TryParse es un método alternativo al anterior. Cuando la conversión es satisfactoria el valor de retorno es true, en caso contrario false. Esto para evitar lanzar una excepción si la conversión falla (Albahari, 2012).

TimeSpan ts;
if (TimeSpan.TryParse("03d:30m:00s", out ts))
{
Console.WriteLine ("Conversión satisfactoria.");
}
else
{
Console.WriteLine ("Conversión insatisfactoria.");
}

6. Ejemplos de Uso

6.1 Creación de objetos

En la salida estándar se muestra la invocación implícita de ToString() para cada uno de los objetos TimeSpan creados con un constructor y la invocación de FromHours:

Console.WriteLine(new TimeSpan (3, 30, 0)); // 03:30:00
Console.WriteLine(TimeSpan.FromHours (3.5)); // 03:30:00
Console.WriteLine(TimeSpan.FromHours (-3.5)); // -03:30:00

6.2 Aritmética con objetos TimeSpan

Los operadores de comparación < y >, así como también los aritmético de adición y sustracción + y - están sobrecargados (Sobrecarga de Operadores en C#) para esta estructura; entonces es posible escribir expresiones como:

TimeSpan.FromHours(3) + TimeSpan.FromMinutes(30);

O;

TimeSpan.FromDays(10) - TimeSpan.FromSeconds(1); // 9.23:59:59

La expresión anterior es equivalente a restar un segundo al intervalo de 10 días.

Ejemplo de uso:

En este ejemplo se muestra una versión extendida de la expresión anterior para demostrar el uso de varias propiedades de TimeSpan:

7. Prueba de Rendimiento

En la siguiente prueba de rendimiento se probará la creación de un objeto TimeSpan a partir de los métodos enlistados en la sección 4: uso de constructor y métodos con prefijo From...:

Aunque los comentarios explican el propósito de las líneas de código más sobresalientes, se resaltan las siguientes características:
  • Línea 11: Para este ejemplo se ejecutan hasta 100 millones de pruebas para cada versión de instanciación de objetos TimeSpan.
  • Los ciclos for de las líneas 17-20, líneas 29-31 y líneas 44-47 ejecuta las pruebas de rendimiento para cada versión de instanciación.
  • Líneas 54-56: Visualización de resultados. El tiempo tomado en milisegundos para cada versión de instanciación de objetos TimeSpan.
En la Figura 2 se muestra los resultados de la ejecución del assembly RendimientoTimeSpan.exe: aquí se observa que el uso del constructor TimeSpan(Int32, Int32, Int32) presenta un mejor desempeño 373ms -ocupa aproximadamente la mitad del tiempo frente a la invocación del método static TimeSpan.FromHours(Int32): 712ms-. La versión de caché -objeto TimeSpan existente en memoria de trabajo- resulta ser la versión más óptima: sólo 79ms para este caso.

Compilación:

csc /t:exe RendimientoTimeSpan.cs

Ejecución assembly:

.\RendimientoTimeSpan.exe

Prueba de ejecución assembly (ideone.com): http://ideone.com/H88dzs

Prueba de ejecución assembly (local):
Ejecución assembly RendimientoTimeSpan.exe
Figura 2. Ejecución assembly RendimientoTimeSpan.exe.

8. Conclusiones

Se ha estudiado la estructura TimeSpan para la representación de intervalos de tiempo. Esta estructura permite la instanciación de objetos TimeSpan usando dos diferentes enfoques: constructor y métodos static. Se mostraron ejemplos de código fuente C# para la aritmética de intervalos usando los operadores + y -. En la sección 7 se midió el rendimiento para: creación de objeto TimeSpan con TimeSpan.FromHours(Int32), uso de constructor -TimeSpan(Int32, Int32, Int32), y modo caché; entre los dos primeros, el uso de constructor resultó más eficiente: reducción de hasta un 50% del tiempo de instanciación.

El próximo artículo de esta serie Manipulación de Fechas y Horas en C# se enfocará en el estudio de la estructura DateTime.

9. Literatura & Enlaces

Albahari, J., Albahari, B. (2012). C# 5.0 in a Nutshell. United States: O'Reilly Media.
TimeSpan Structure (System) (2016, mayo 20). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.timespan.aspx.
C# TimeSpan Examples (2016, mayo 20). Recuperado desde: http://www.dotnetperls.com/timespan
Sobrecarga de Operadores en C# (2016, mayo 20). Recuperado desde: http://ortizol.blogspot.com.co/2014/09/sobrecarga-de-operadores-en-csharp.html
TimeSpan.Parse Method (System) (2016, mayo 20). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.timespan.parse%28v=vs.110%29.aspx


V