You should be automatically redirected . If not, visit
http://newlisper.wordpress.com
and update your bookmarks.

27/06/2008

Dated posts

You'll sometimes see the date and time presented in this format - 2008-04-19T22:45:33Z. It's the date (year-month-day) followed by a "T", followed by the time (hours:minutes:seconds), followed by a Z, which specifies the Greenwich or UT Time Zone. ('Z' stands for 'Zulu', but that's another, and possibly more interesting, story.) This date-time format conforms to the Atom Date construct, as described in the Atom specification:

A Date construct is an element whose content MUST conform to the "date-time" production in RFC3339. In addition, an uppercase "T" character MUST be used to separate date and time, and an uppercase "Z" character MUST be present in the absence of a numeric time zone offset.

atomDateConstruct =
   atomCommonAttributes,
   xsd:dateTime

Such date values happen to be compatible with the following specifications: ISO.8601.1988, W3C.NOTE-datetime-19980827, and W3C.REC-xmlschema-2-20041028.

and here's ISO 8601:

The following profile of ISO 8601 dates SHOULD be used in new protocols on the Internet. This is specified using the syntax description notation defined in ABNF.


     date-fullyear   = 4DIGIT
     date-month      = 2DIGIT  ; 01-12
     date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on
                               ; month/year
     time-hour       = 2DIGIT  ; 00-23
     time-minute     = 2DIGIT  ; 00-59
     time-second     = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second
                               ; rules
     time-secfrac    = "." 1*DIGIT
     time-numoffset  = ("+" / "-") time-hour ":" time-minute
     time-offset     = "Z" / time-numoffset
    
     partial-time    = time-hour ":" time-minute ":" time-second
                       [time-secfrac]
     full-date       = date-fullyear "-" date-month "-" date-mday
     full-time       = partial-time time-offset
    
     date-time       = full-date "T" full-time

Important stuff!

In newLISP, you can get time in this format by using a suitable time format string with date. For example, the modification time of a file can be presented in RFC3339 date-time format with this:

(set 'modification-date (date file-mod-date 0 "%Y-%m-%dT%H:%M:%SZ"))

where file-mod-date is the file's modification date as a seconds-from-1970 value, obtained like this:

(set 'file-mod-date (file-info file 6))

The previous blogging tool I wrote made extensive use of compressed ISO 8601 identifiers:

20080419224533

which is a 14-digit number or string. It can be used as either:

(set 'p 20080419224533)
(dec 'p)
;-> 20080419224532
(set 'p "20080419224533")
(length p)
;-> 14

I used this both as the unique identifier for a post or blog entry, and as the publication date. To convert these compressed 14 digit ISO date-times (and others) to a newLISP seconds-from-1970 value, you can use parse-date:

(parse-date "20080419224533" "%Y%m%d%H%M%S")
;-> 1208645133

(date (parse-date "20080419224533" "%Y%m%d%H%M%S"))
;-> "Sat Apr 19 23:45:33 2008"

The first problem is that parse-date on MacOS X systems appears to have some flaws. Lutz reckons that libc.dylib on Mac OS X was broken for the strptime() function somewhere between MacOS X 10.4 (Tiger) and 10.5 (Leopard). It was apparently the case that, for some versions of newLISP and MacOS X, the conversion of compressed ISO8601 identifiers didn't work:

(parse-date "20080411234423" "%Y%m%d%H%M%S") 
;-> nil 

Suddenly being unable to read date strings without spaces, I spent a few minutes writing a parse-iso-date function:

(define (parse-iso-date s)
 (let ((y (pop s 0 4))
       (m (pop s 0 2))
       (d (pop s 0 2))
       (h (pop s 0 2))
       (mn (pop s 0 2))
       (sec s))
 (parse-date (format "%s %s %s %s %s %s" y m d h mn sec) "%Y %m %d %H %M %S")))

but it doesn't look like the right solution - just reformatting a string so that it has spaces between the components and then using parse-date. And later I found that I was converting between different date formats too often: from compressed ISO to Atom, or from compressed ISO to a familiar local representation, and then back into Atom again.

When you stare at a problem for long enough, you can often see a bigger problem hidden behind it. I started to dislike seeing these IDs. References to stories used to take the form:

index.cgi?post-id=20080411234423

which is computer-friendly but user-hostile, easy enough for a computer to produce but not easy for humans to recognise or decipher. I've typed enough of these in by hand to know that it's surprisingly easy to lose your place in a long string of digits when you're tired or in a hurry. Another problem is updating a post makes these date-based IDs less meaningful - but changing them probably isn't the right solution either.

So, for the current blogging script, I've adopted a different approach. Stories are referred to using more readable URLs - I read that this was A Good Idea. Dates are now a part of the metadata but extracted and displayed when required, with more emphasis on how old something is rather than the exact moment it was written. And hopefully it's no longer necessary to display weird date formats just because they're used internally by the software.

0 Comments:

Post a Comment

Links to this post:

Create a Link

<< Home