随着Google Reader的终结,最近考虑做一个程序用于读取独立博客的最新文章和内容,以方便自己能够及时的获得所需要的信息。实现这样一个程序并不困难,使用xml文档读取rss的路径就ok了。但是我在将rss的时间格式,转化为标准的东八区的时候遇到了困难,delphi或者很多其他的程序语言并不存在类似的库类支持这样子的转换,万般无奈就只好自己搞了。
rss时间规范
rss的时间规范是遵从RFC822规范的,RFC822是标准的邮件协议。1977年,Arpnet在他们开发的几个非正式文本消息传送标准的基础上,制订了“Arpnet网络之间文本消息格式标准”,即RFC#733。后来为了适应更大、更复杂的Arpnet网,对RFC#733作了一些修订,形成了RFC#822。虽然RFC#822是专门为Arpnet网设计的,但其他网络之间的文本消息传输也可以用。
其中规定的时间格式为:Date: Thu, 18 Jan 2001 14:21:34 +0800 (CST)
具体的规范如下:
date-time = [ day “,” ] date time ; dd mm yy; hh:mm:ss zzz
day = “Mon” / “Tue” / “Wed” / “Thu”/ “Fri” / “Sat” / “Sun”
date = 1*2DIGIT month 2DIGIT ; day month year; e.g. 20 Jun 82
month = “Jan” / “Feb” / “Mar” / “Apr”/ “May” / “Jun” / “Jul” / “Aug”/ “Sep” / “Oct” / “Nov” / “Dec”
time = hour zone ; ANSI and Military
hour = 2DIGIT “:” 2DIGIT [“:” 2DIGIT]; 00:00:00 – 23:59:59
zone = “UT” / “GMT” ; Universal Time;
North American : UT/ “EST” / “EDT” ;
Eastern: – 5/ – 4/ “CST” / “CDT” ;
Central: – 6/ – 5/ “MST” / “MDT” ;
Mountain: – 7/ – 6/ “PST” / “PDT” ;
Pacific: – 8/ – 7/ 1ALPHA ;
Military: Z = UT;
A:-1; (J not used);
M:-12;
N:+1;
Y:+12/ ( (“+” / “-“) 4DIGIT ) ; Local differential
这里面关于时区的概念很复杂可以是“+”或者“-”接后面四个数字,也可以是以上的这么多专用代码,大部分代表的是美国不同地区如东西部地区的时区字母缩写,整理一下就是就是:
EDT is 相等于 -0400
EST is 相等于 -0500
CDT is 相等于 -0500
CST is 相等于 -0600
MDT is 相等于 -0600
MST is 相等于 -0700
PDT is 相等于 -0700
PST is 相等于 -0800
编程思路
知道大概的思路之后,我们就开始着手进行编程,将rss的时间格式转化为标准时间格式:
1、分割字符串,由于以上的格式标准是用”,”和空格进行分割的,我们就利用其空格将其分割为5个字符串。
2、将分割的第二个字符串即月份从英文缩写格式转换为数字格式。
3、组合前四个字符串,格式化为标准时间。
4、处理第五个字符串即时区,计算应该加减的时间。
5、与组合的标准时间加减得到东八区的时间。
上图的最下面的时间已经转化为了东八区的标准时间
具体的代码如下,(注:此版本只处理了标准的时区格式,如有需要请自行再处理)
function StringToList(AText: string; Splitter: string): TStrings; begin result := TStringList.Create; result.Text := StringReplace(AText, Splitter, sLineBreak, [rfReplaceAll]); end; function GetDate(AXmlDate: string): TDateTime; var fDate: string; fYear, fMonth, fDay, fTime,fUtc: string; fList: TStrings; function GetMonth(AName: string): String; var fMonth: Integer; begin if AName = 'Jan' then fMonth := 1 else if AName = 'Feb' then fMonth := 2 else if AName = 'Mar' then fMonth := 3 else if AName = 'Apr' then fMonth := 4 else if AName = 'May' then fMonth := 5 else if AName = 'Jun' then fMonth := 6 else if AName = 'Jul' then fMonth := 7 else if AName = 'Aug' then fMonth := 8 else if AName = 'Sep' then fMonth := 9 else if AName = 'Oct' then fMonth := 10 else if AName = 'Nov' then fMonth := 11 else if AName = 'Dec' then fMonth := 12 else fMonth := 0; if (fMonth > 0) then begin result := IntTostr(fMonth); if (fMonth < 10) then result := '0' + IntTostr(fMonth); end; end; begin if (AnsiPos(',', AXmlDate) > 0) or (AnsiPos('GMT', AXmlDate) > 0) then begin //The date format is :ddd, dd mmm yyyy hh:mm:ss zzz fDate := Copy(AXmlDate, AnsiPos(',', AXmlDate) + 1, Length(AXmlDate)); fDate := Trim(fDate); fList := StringToList(fDate, #32); try if fList.Count >= 4 then begin fDay := fList[0]; fMonth := GetMonth(fList[1]); fYear := fList[2]; fTime := fList[3]; fDate := Format('%s-%s-%s %s', [fyear, fMonth, fDay, fTime]); fUtc:= StringReplace(fList[4],'+','',[rfReplaceAll]); fUtc:= StringReplace(fUtc,'0','',[rfReplaceAll]); if fUtc='' then fUtc:='0'; if (8-strtoint(fUtc))>=0 then begin fDate:=DateTimeToStr(strtodatetime(fdate)+strtodatetime(inttostr(8-strtoint(fUtc))+':00:00')); end else begin fDate:=DateTimeToStr(strtodatetime(fdate)-strtodatetime(inttostr(strtoint(fUtc)-8)+':00:00')); end; end; finally // free resources fList.Free; end; // try/finally end else fDate := AXmlDate; result := StrToDateTime(fDate); end;
如无特别说明,本博客文章皆为原创。转载请说明,来自吵吵博客。
原文链接:http://chaochaoblog.com/archives/1902
吵吵微信朋友圈,请付款实名加入: