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.
¿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:
<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 <a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm">Star City</a>.</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 <a href="http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm">partial eclipse of the Sun</a> 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”
Ta chido su site compa. Siga subiendo articulos, que seguramente a alguien algun dia le van a servir.
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
pero ta chido.
[...] HH:MM:SS con su respectivo tiempo en meridiano (“a.m.” o “p.m.”) usando las funciones que desarrolle anteriormente [...]
Deja un comentario...