Convertidor de fechas en RFC822 a Zona Horaria

Actualmente me encuentro trabajando en el desarrollo de un programa lector de RSS (Really Simple Syndication) o Feeds para Windows y una pequeña parte de su desarrollo implica la transformación de fechas a la zona horaria del cliente. El programa en cuestión lo estoy desarrollando con Delphi 2009, un magnifico lenguaje/IDE al que me he venido afanando por los últimos 7 años.

Captura de Pantalla de Aplicacion

Captura de Pantalla de Aplicacion

Descargar Archivos

Descargar Aplicacion

¿Qué es la especificación RFC822?

Bueno pues el RFC822 es un documento que especifica normas sobre el formato para el envió de mensajes por Internet, comúnmente e-Mail u otros medios. La finalidad como todo estándar es la de garantizar la homogeneidad enlas estructuras utilizadas para enviar información.

Un sencillo ejemplo de la estructura XML para RSS 2.0 es:

<?xml version="1.0"?>
<rss version="2.0">
   <channel>
      <title>Liftoff News</title>
      <link>http://liftoff.msfc.nasa.gov/</link>
      <description>Liftoff to Space Exploration.</description>
      <language>en-us</language>
      <pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate>

      <lastBuildDate>Tue, 10 Jun 2003 09:41:01 GMT</lastBuildDate>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs>
      <generator>Weblog Editor 2.0</generator>
      <managingEditor>editor@example.com</managingEditor>
      <webMaster>webmaster@example.com</webMaster>
      <item>

         <title>Star City</title>
         <link>http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp</link>
         <description>How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's &lt;a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm"&gt;Star City&lt;/a&gt;.</description>
         <pubDate>Tue, 03 Jun 2003 09:39:21 GMT</pubDate>
         <guid>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573</guid>

      </item>
      <item>
         <description>Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a &lt;a href="http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm"&gt;partial eclipse of the Sun&lt;/a&gt; on Saturday, May 31st.</description>
         <pubDate>Fri, 30 May 2003 11:06:42 GMT</pubDate>
         <guid>http://liftoff.msfc.nasa.gov/2003/05/30.html#item572</guid>

      </item>
      <item>
         <title>The Engine That Does More</title>
         <link>http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp</link>
         <description>Before man travels to Mars, NASA hopes to design new engines that will let us fly through the Solar System more quickly.  The proposed VASIMR engine would do that.</description>
         <pubDate>Tue, 27 May 2003 08:37:32 GMT</pubDate>
         <guid>http://liftoff.msfc.nasa.gov/2003/05/27.html#item571</guid>

      </item>
      <item>
         <title>Astronauts' Dirty Laundry</title>
         <link>http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp</link>
         <description>Compared to earlier spacecraft, the International Space Station has many luxuries, but laundry facilities are not one of them.  Instead, astronauts have other options.</description>
         <pubDate>Tue, 20 May 2003 08:56:02 GMT</pubDate>
         <guid>http://liftoff.msfc.nasa.gov/2003/05/20.html#item570</guid>

      </item>
   </channel>
</rss>

RSS 2.0 es otra especificación para la conocida estructura XML de un documento para Feeds, dentro del cual se dice que para la delcaración de las fechas se debe usar las especificación RFC822 dentro de las etiquetas <pubDate></pubDate (aunque existen criticas del porque no se ha migrado a la especificación 2822) mira el documento original aca.

El Código

He diseñado dos unidades de código: la primera “DateTimeConversion.pas” cuenta con 3 funciones:

  • “ConvertZone( Zone : string ) : Integer” que retorna el cambio de horario en minutos según la Zona dada como por ejemplo: GMT, EST, PDT, etc. o bien +0000, -0500, -0700.
  • “RFC822ToDateTime( val : string ) : TDateTime” que devuelve la fecha transformada según la zona horaria del cliente local tomando como parámetro una cadena con la fecha en formato “RFC822”.
  • “DateToSpanish( date : TDateTime ) : string” Una función muy sencilla para transformar una fecha de tipo TDateTime al formato español como por ejemplo: “Lunes 22 de Junio de 2009”

Y la segunda unidad de código “MiscDateTime” que contiene 2 funciones bastante sencillas:

  • “GetTimeZone : integer” que devuelve la zona horaria usada por el cliente local con compensación de horario de verano. Así por ejemplo si la llamo desde mi PC devuelve -5 que se refiere a las horas que tenemos que restar a la Hora Central GMT/UTC.
  • “GetUTCTime : TDateTime” que retorna el horario GMT/UTC actual, calculado en base a la zona horaria actual.

Y bueno aquí el código de las 2 unidades:

(*
 *
 * Nombre: DateTimeConversion.pas
 * Fecha: Lunes 22 de Junio del 2009
 * Autor: Iván Juárez Núñez
 * eMail: radix@redmater.com
 * Pagina: www.redmater.com
 *
 * Unidad de codigo que muestra como hacer conversiones de tiempo para las distintas
 * zonas horarias del mundo en base a el formato UTC o Greenwich Mean Time usando la
 * especificacion RFC822 que puede ser encontrada en http://www.w3.org/Protocols/rfc822/#z28
 *
 * Este codigo se ofrece sin ninguna garantia y puede ser usado/modificado/redistribuido
 * con la unica condicion de incluir al autor en sus creditos.
 *)


unit DateTimeConversion;

interface
  uses SysUtils, StrUtils, DateUtils;

  FUNCTION ConvertZone(Zone:string):Integer;
  FUNCTION RFC822ToDateTime(val:string):TDateTime;
  FUNCTION DateToSpanish(date:TDateTime):string;

CONST
 ZoneCodes: Array[0..9] of Record
 Name: String;
 Time: ShortInt;
 end =
 ((Name:'UT' ; Time:0),
 (Name:'GMT' ; Time:0),
 (Name:'EST' ; Time:-5),
 (Name:'EDT' ; Time:-4),
 (Name:'CST' ; Time:-6),
 (Name:'CDT' ; Time:-5),
 (Name:'MST' ; Time:-7),
 (Name:'MDT' ; Time:-6),
 (Name:'PST' ; Time:-8),
 (Name:'PDT' ; Time:-7));

 implementation
uses
 MiscDateTime;

//Convierte una Zona por numero o texto: PDT, UT, GMT o +0000,+0600, etc a minutos
FUNCTION ConvertZone(Zone:string):Integer;
var
i: Byte;
ZoneConv: Integer;
BEGIN
ZoneConv := 0;

try
Zone := AnsiUpperCase(Trim(Zone));

 if (Zone[1]='+')OR(Zone[1]='-') then
 begin
   ZoneConv := (StrToInt(Zone[2]+Zone[3])*60)+StrToInt(Zone[4]+Zone[5]);
   if (Zone[1]='-') then
      ZoneConv := ZoneConv * -1;
 end;
 for i := 0 to Length(ZoneCodes) - 1 do
  if ZoneCodes[i].Name = Zone then
    ZoneConv := ZoneCodes[i].Time*60;
except
On Exception: EConvertError do
 ZoneConv := 0;
end;

result := ZoneConv;
END;
//Convierte el formato de Hora y Fecha RFC822 a TDateTime
FUNCTION RFC822ToDateTime(val:string):TDateTime;
var
 idx: byte;
 DateTimeC: TDateTime;
 Day,Year,Month,Time,Zone: string;
const
 Days: array[0..6] of string =
 ('SUN, ','MON, ','TUE, ','WED, ','THU, ','FRI, ','SAT, ');
 Months: array[0..11] of string =
 ('JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC');
BEGIN

val := AnsiUpperCase(val);

for idx := 0 to Length(Days) - 1 do
  val := AnsiReplaceStr(val,Days[idx],'');

  {Podriamos usar un array y un for pero es preferible
  dejarlo asi para hacer el codigo mas mantenible}


  Day := Trim(Copy(val, 1, AnsiPos(' ', val)));
  Delete(val,1,Length(Day)+1);

  Month := Trim(Copy(val, 1, AnsiPos(' ', val)));
  Delete(val,1,Length(Month)+1);

for idx := 0 to Length(Months) - 1 do
  Month := AnsiReplaceStr(Month,Months[idx],IntToStr(idx+1));
{Si la año esta declarado en 2 digitos lo pasamos a 4}
  Year := Trim(Copy(val, 1,AnsiPos(' ',val)));
  Delete(val,1,Length(Year)+1);
  if (StrToInt(Year)<1000) then
    Year := IntToStr(StrToInt(Year)+2000);

  Time := Trim(Copy(val, 1,AnsiPos(' ',val)));
  Delete(val,1,Length(Time)+1);
  DateTimeC := StrToDateTime(Day+'/'+Month+'/'+Year+' '+Time);

  Zone := Trim(Copy(val,1,Length(val)));
{Convertimos la fecha RFC9822 al cambio horario nuestro}
  DateTimeC := IncSecond(DateTimeC,GetTimeZone*3600);

result := DateTimeC;
END;
//Convierte una Fecha TDateTime con formato DD/MM/AAAA a formato Español
//como: Lunes, 23 de Agosto del 2009
FUNCTION DateToSpanish(date:TDateTime):string;
VAR
Year, Month, Day: word;
CONST
Dias: Array[1..7] of String =
('Domingo','Lunes','Martes','Miercoles','Jueves','Viernes','Sabado');
Meses: Array[1..12] of String =
('Enero','Febero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre',
'Octubre','Noviembre','Diciembre');
BEGIN
DecodeDate(date,Year,Month,Day);

  Result := Dias[DayOfWeek(date)]+', '+InttoStr(Day)+' de '+Meses[Month]+' de '+ IntToStr(Year);
END;

end.
(*
 *
 * Nombre: MiscDateTime.pas
 * Fecha: Lunes 22 de Junio del 2009
 * Autor: Iván Juárez Núñez
 * eMail: radix@redmater.com
 * Pagina: www.redmater.com
 *
 * Diversas funciones para obtener datos relacionados a la fecha y hora
 *
 * Este codigo se ofrece sin ninguna garantia y puede ser usado/modificado/redistribuido
 * con la unica condicion de incluir al autor en sus creditos.
 *)


unit MiscDateTime;

interface
  uses DateUtils, SysUtils, Windows;

FUNCTION GetTimeZone: integer;
FUNCTION GetUTCTime: TDateTime;

implementation

{ Obtiene la Zona Horaria usada por el Sistema }
FUNCTION GetTimeZone: integer;
var
  TimeZone: TTimeZoneInformation;
BEGIN
  GetTimeZoneInformation(TimeZone);
  Result := (TimeZone.Bias+TimeZone.DaylightBias+TimeZone.StandardBias) div -60;
END;
{ Obtiene el Tiempo local  GTM +0}
FUNCTION GetUTCTime:TDateTime;
BEGIN
   result := IncSecond(Now,3600*GetTimeZone);
END;

end.

La verdad es que esta aplicación no tiene utilidad práctica por sí sola, pero si te encuentras desarrollando algún tipo de programa que tenga que lidiar con este tipo de formatos entonces puede serte útil y ahorrarte unas horillas de programación.

3 Respuestas to “Convertidor de fechas en RFC822 a Zona Horaria”

  1. CronNo Gravatar
    junio 23, 2009 at 11:43

    Ta chido su site compa. Siga subiendo articulos, que seguramente a alguien algun dia le van a servir. :D   
    Citar
      Responder

  2. schmidtNo Gravatar
    junio 23, 2009 at 16:50

    El programa para cambiar ip a mi si me hace paro y mas ahora que estoy descargando arto comic… yo estoy teniendo unos problemas con fechas en algo que hago pero mmmm nop, esto no lo puedo aplicar jejeje son cosas muy diferentes :P pero ta chido.  
    Citar
      Responder

  3. Simple Lector de Noticias RSS en Delphi | RedMater.com - Información Destilada de Software y Tecnología
    junio 24, 2009 at 1:48

Deja un comentario...

 Caracteres máximo
free blog themes