Norma ISO 8601, duration y .NET
No es que tenga que ser habitual, pero podría ocurrir como a mí me ha pasado, que tengas que utilizar y recurrrir a la norma ISO 8601 dentro de un proyecto .NET.
La norma ISO 8601 que se publicó el 3 de Diciembre de 2004 tiene el siguiente título en inglés:
Data elements and interchange formats — Information interchange — Representation of dates and times
Y no es otra cosa que la representación, de acuerdo una notación estándar, de intervalos recurrentes en el tiempo dentro del calendario Gregoriano con el fin de evitar ambigüedades.
Utilizar esta notación evita problemas de ambigüedades, migraciones e interpretaciones de la ocurrencia a llevar a cabo.
La notación cubierta en esta norma ISO entiende periodos que comprenden años, meses, días, horas, minutos y segundos.
Desde hace muchísimos años, en mis ficheros locales y en proyectos Software he seguido por lo general el patrón YYYYMMDD-HHMMSS.
Una de las razones principales es la ordenación de los datos. Otra es la búsqueda.
Pero la norma ISO 8601 va más allá que esto que ya lo contempla.
Además de la representación de fechas y horas con las que estamos habituados a trabajar, como por ejemplo el uso del carácter Z al final para representar una fecha/hora en formato UTC, tenemos la posibilidad de utilizar representaciones de fecha/hora con señaladores.
Es precisamente aquí, dónde quiero hacer hincapié en este artículo.
El formato de la norma ISO 8601 para representar fechas y horas con representación de señaladores es de la siguiente forma:
PnnYnnMnnDTnnHnnMnnS
La explicación más o menos detallada de este patrón es la siguiente:
- Todas las representaciones empezarán por P que indica Period o Período.
- Cada valor, va seguido de lo que representa.
- Así, si ponemos 2 años, indicaremos 02Y ó 2Y.
- El caso de las horas es el mismo con la salvedad de que al principio, deberemos indicar una T que indica Time o tiempo.
Así, podríamos representar la ocurrencia:
P1Y2M3DT1H2M3S
O lo que es lo mismo, 1 año, 2 meses, 3 días, 1 hora, 2 minutos y 3 segundos.
Para ponernos en contexto, imaginemos que queremos saber cuando ocurrirá una ocurrencia de acuerdo a la representación de señaladores, duraciones, o Durations en inglés.
Imaginemos por lo tanto que vamos a escribir esto en C#.
Recogeríamos la fecha/hora actual por poner un ejemplo, aunque lo lógico es que esto no se realice así, y lo hago de esta manera para mostrar la operativa ocasional que realizaríamos.
DateTime date = DateTime.Now;
Crearíamos una variable que defina el patrón de este modo (que también sería obtenido con un servicio, etc):
string pattern= "P1Y2M3DT1H2M3S";
A continuación, deberíamos «por lógica», convertir ese patrón en un TimeSpan.
TimeSpan ts = ConvertToTimeSpan(pattern);
Y finalmente, calcularíamos la fecha/hora en la que se aplicará el suceso.
DateTime dateOccurrence = date.Add(ts);
El problema aquí, es que .NET no tiene dentro del objeto TimeSpan ni dentro de DateTime, nada que nos permita llevar a cabo esta operativa.
Así que,… ¿cómo podríamos resolver esto?.
Pues básicamente con ayuda de System.Xml.
Sonará raro, pero con System.Xml sí es posible trabajar con la norma ISO 8601 y con representación de señaladores, ya que está preparado para ello, así que en resumen… es nuestro aliado y amigo para resolver nuestro problema.
Dentro de System.Xml encontraremos dos métodos:
XmlConvert.ToString que convertirá un TimeSpan a representación de señaladores.
XmlConvert.ToTimeSpan que convertirá una representación de señaladores a TimeSpan.
Así que, el ejemplo anterior podría quedar de la siguiente forma para pasar de una representación de señaladores a DateTime:
DateTime date = DateTime.Now; string pattern = "P1Y2M3DT1H2M3S"; TimeSpan ts = XmlConvert.ToTimeSpan(pattern); DateTime dateOccurrence = date.Add(ts); Console.WriteLine($"format => {pattern} => {date} => {dateOccurrence}"); Console.ReadLine();
Y en el caso de pasar de TimeSpan a representación de señaladores, podríamos hacerlo de esta otra forma:
string pattern = XmlConvert.ToString(new TimeSpan(1, 21, 0, 10));
En este caso, estaríamos representando 1 día, 21 horas y 10 segundos.
Siendo la salida de la representación de señaladores o duración:
P1DT21H10S
El problema aquí no obstante, podría ser que TimeSpan no representa años ni meses, por lo que no cumple con exactitud lo que se esperaría de la ISO 8601, pero por otro lado, debo decir que funciona correctamente el viaje de ida y vuelta.
Para más información, te sugiero acceder al enlace que sobre la norma ISO 8601 encontrarás en la Wiki en este enlace.
¡Happy Coding!