Dátumok standard módon

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.

 

Technorati tags: ,

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s