Aki az életben már legalább egyszer megnyerte azt a nemes feladatot, hogy egy weboldalhoz RSS feedet készítsen, biztosan belefutott a dátumformázással kapcsolatos macerákba. Az RSS 2.0 szabvány szerint a dátumoknak, például a pubDate mezőnek az RFC 822 "szabványt" (ami 1982. augusztus 13. óta létezik!) kell követniük:
All date-times in RSS conform to the Date and Time Specification of RFC 822, with the exception that the year may be expressed with two characters or four characters (four preferred).
Azaz például (szintén a szabványból):
Sat, 07 Sep 2002 00:00:01 GMT
Nézzünk egy kicsit jobban utána ennek, konkrétan az RFC 822 (STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES) ötödik, Date and Time Specification fejezete foglalkozik a dátum- és idő formátummal. Nem hoszzú, idemásolom:
5. DATE AND TIME SPECIFICATION
5.1. SYNTAX
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
; hours+min. (HHMM)
5.2. SEMANTICS
If included, day-of-week must be the day implied by the date
specification.
Time zone may be indicated in several ways. "UT" is Univer-
sal Time (formerly called "Greenwich Mean Time"); "GMT" is per-
mitted as a reference to Universal Time. The military standard
uses a single character for each zone. "Z" is Universal Time.
"A" indicates one hour earlier, and "M" indicates 12 hours ear-
lier; "N" is one hour later, and "Y" is 12 hours later. The
letter "J" is not used. The other remaining two forms are taken
from ANSI standard X3.51-1975. One allows explicit indication of
the amount of offset from UT; the other uses common 3-character
strings for indicating time zones in North America.
Hogyan lehetne ezt előállítani .NET-ben, hiszen nincs közvetlenül olyan dátumformátumunk, ami pont ilyen lenne. Próbáljuk összerakni:
Console.WriteLine( DateTime.Now.ToString("ddd, dd MMM yyyy HH:mm:ss zzz") );
Ebből ez lesz a konzolon, ami nem éppen az igazi:
Cs, 30 aug. 2007 11:41:39 +02:00
Írhatunk hozzá hosszabb kódot, például így (vagy akár szebben is):
public static string ToRfc822String( DateTime date )
{
int offset = TimeZone.CurrentTimeZone.GetUtcOffset( DateTime.Now ).Hours;
char sign = '+';
if( offset < 0 )
{
sign = '-';
offset = offset * -1;
}
string zone = ( sign + offset.ToString().PadLeft( 2, '0' ) ).PadRight( 5, '0' );
return date.ToString( "ddd, dd MMM yyyy HH:mm:ss " + zone, CultureInfo.InvariantCulture );
}
Külön figyelmet érdemel az InvariantCulture alkalmazása, enélkül ugyanis szép magyar hónap és nap nevek jönnének, mivel azonban a kultúra információkért felelős .NET fejlesztő csapat szerint, ha valami invariáns, akkor legyen angol, éppen rendben vagyunk:
Thu, 30 Aug 2007 11:05:13 +0200
Bár a fenti kódrészletet valószínűleg meg lehet írni szebben és tömörebben, rutinos .NET fejlesztő nehezen hiszi el, hogy erre nem gondoltak a keretrendszer fejlesztői és saját függvény írására vagyunk kárhoztatva. Alaposabban nézegetve az MSDN Standard DateTime Format Strings fejezetét feltűnhet egy formátum, ami kilóg a sorból:
R or r: RFC1123 pattern
Represents a custom DateTime format string defined by the current RFC1123Pattern property. The pattern is a defined standard and the property is read-only. Therefore, it is always the same regardless of the culture used or the format provider supplied.
The custom format string is "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'".
Formatting does not modify the value of the DateTime object that is being formatted. Therefore, the application must convert the value to Coordinated Universal Time (UTC) before using this format specifier.
Hm, ez a formátum kísértetiesen hasonlít az RFC 822 formátumára, nézzük csak meg, hogy mit mond az 1989. októberéből származó RFC 1123, ami a "Requirements for Internet Hosts - Application and Support" címre hallgat! Ennek az 5.2.14 Date and Time Specification fejezete közvetlenül hivatkozik az RFC 822 Section 5-re, némi kiegészítéssel:
The syntax for the date is hereby changed to:
date = 1*2DIGIT month 2*4DIGIT
All mail software SHOULD use 4-digit years in dates, to ease
the transition to the next century.
There is a strong trend towards the use of numeric timezone
indicators, and implementations SHOULD use numeric timezones
instead of timezone names. However, all implementations MUST
accept either notation. If timezone names are used, they MUST
be exactly as defined in RFC-822.
The military time zones are specified incorrectly in RFC-822:
they count the wrong way from UT (the signs are reversed). As
a result, military time zones in RFC-822 headers carry no
information.
Finally, note that there is a typo in the definition of "zone"
in the syntax summary of appendix D; the correct definition
occurs in Section 3 of RFC-822.
Tehát a különbségek:
- 4 digites évszámokat kell használni
- Számokkal kell leírni az időzónákat.
Ez kibírható, próbáljuk ki!
Console.WriteLine( DateTime.Now.ToUniversalTime().ToString( "R" ) );
A kimenet pedig ez lesz:
Thu, 30 Aug 2007 09:23:15 GMT
A kérdés tehát: kell-e saját dátumformázó függvényt írnunk, vagy jó lesz a ToString("R") is?
A fentiek alapján elmondhatjuk, hogy a beépített dátumformátum megfelel az RSS előírásainak, tehát használható, sőt valószínűleg ez a legegyszerűbb megoldás. Ugyanakkor meg kell jegyeznünk, hogy a keretrendszer nem követi teljesen az RFC 1123-at, mert nem numerikus időzóna meghatározásokat használ.