greghendershott / frog

Frog is a static blog generator implemented in Racket, targeting Bootstrap and able to use Pygments.
918 stars 96 forks source link

Date formatting weirdness #240

Closed toothbrush closed 5 years ago

toothbrush commented 5 years ago

Hello again, and apologies upfront if this is PEBKAC.

I'm trying to modify the way dates get printed out. I have seen and read the bit in the tutorial which specifically outlines how to do this: 5.4 Template Example.

Inspired, i thought i could use Racket's builtin (display-date-format) and went right ahead: (this works)

@(parameterize ([display-date-format 'german])
  @(date->string date-struct))

However, none of the small handful of builtin formats suited my needs. Then, on a very obscure email thread i saw that you could use ~a-like format strings. The Racket docs are coy about this (perhaps i'm looking wrong: date->string docs in 15.6 Time). However i stumbled across a reference to "srfi/19", which talks about being able to use format strings – exactly what i want! However, the following code:

@(local-require racket/date)
...
      <time datetime='@|date-8601|' pubdate='true'>
          @(date->string date-struct "~e ~B ~Y")
      </time>

produces

      <time datetime='2019-01-02T00:00:00' pubdate='true'>
          Sunday, January 2nd, 2019 12:00:00am
      </time>

Ignoring the fact that January the 2nd was actually a Wednesday (this really caused me to question my sanity for a long hard while) – but i'm guessing that's because the date struct's day field is not computed properly¹ and defaults to 0 or Sunday, this is not the format i asked for. What could be the matter?

  1. This strikes me as a problem in the racket/date library. Is it worth reporting there?
toothbrush commented 5 years ago

I don't know if this counts as a solution to the weirdness above per se, but it solved my particular niche issue so i thought i'd share it here for anybody else who might stumble across it.

I ended up using a Racket library called gregor – i created a date struct (not to be confused with the date from racket/date...) and used gregor's formatting system. The format codes are helpfully described here.

@(local-require gregor)
...
      <time datetime='@|date-8601|' pubdate='true'>
        @(~t (date
               (date-year date-struct)
               (date-month date-struct)
               (date-day date-struct))
             "E d MMMM y")
      </time>

produces

      <time datetime='2019-01-03T00:00:00' pubdate='true'>
       Thu 3 January 2019
      </time>

It's definitely hacky, but it solves my issue. Note that it also correctly figured out that the 3rd of Jan is a Thursday and not a Sunday.

sorawee commented 5 years ago

This is Frog's bug. See:

https://github.com/greghendershott/frog/blob/2bc070a60333e1316ff713f9b9b577a7c27e54b3/frog/private/bodies-page.rkt#L172-L174

The right way to do this is to use find-seconds rather than construct a date object manually. I will submit a PR soon.

greghendershott commented 5 years ago

@sorawee Thanks for the fix!

@toothbrush I nudged the Racket package server to refresh. You can get with raco pkg update --update-deps frog.

toothbrush commented 5 years ago

Cool, thank you! As i understand it, that'll solve the Sunday issue, but not the issue where the date format string gets ignored / misinterpreted?

sorawee commented 5 years ago

@toothbrush I think you need to use date->string from the srfi/19 package rather than racket/date. Is this what you want?

$ racket
Welcome to Racket v7.1.
> (require srfi/19)
> (date->string (current-date) "~e ~B ~Y")
" 4 January 2019"

(in the template file, you probably need to use @(local-require srfi/19) instead).

toothbrush commented 5 years ago

Ah geez, thanks @sorawee, that's it. Stupidly i didn't realise that srfi/19 was its own library. Done! 🙌