Gregor: a date and time library for Racket
and find it to be very powerful and useful.
In my current application (digging through mail headers) I'm wondering whether there is a way to test whether a given date-time format matches without using exceptions. (I assume that would generally be more efficient than catching exceptions.)
I've forked https://github.com/97jaz/gregor
and successfully added a couple of tests that work to tests/parse.rkt:
(test-suite
"some datetime particulars"
(check-equal?
(parse-datetime "2015-03-15T02:02:02-04:00" "yyyy-MM-dd'T'HH:mm:ssxxx") (datetime 2015 3 15 2 2 2))
(parameterize ([current-locale "en"])
(check-equal?
(parse-datetime "21 Jun 2015 15:45:40" "dd MMM yyyy HH:mm:ss") (datetime 2015 6 21 15 45 40)))
(check-exn
exn:gregor:parse?
(lambda ()
(parse-datetime "21 Jun 2015 15:45:40 -0000" "yyyy-MM-dd'T'HH:mm:ssxxx")))
)
I'd like to add something along these lines:
(check-equal?
(parsable-as-datetime? "2015-03-15T02:02:02-04:00" "yyyy-MM-dd'T'HH:mm:ssxxx")
#t)
(check-equal?
(parsable-as-datetime?"21 Jun 2015 15:45:40 -0000" "yyyy-MM-dd'T'HH:mm:ssxxx")
#f)
but implementing them would take me longer than I have at the moment. (Maybe using an err lambda that doesn't throw an exception?)
I thought I'd check here:
- does this seem like a reasonable idea?
- is mine an unusual use case and most folks know what format to expect and the exception approach is fine?
- is there perhaps an elegant way for me to test with a regular expression first rather than adding this function to Gregor?
Cheers,
Tim
I'd still be curious what folks think about an approach avoiding exceptions.
I agree with your analysis and thoughts about which cases should always raise exceptions. (I can't recall whether you scan patterns that include semi-redundant information such as day-of-week; wondered just now whether a contradictory day of week would be another category of exception -- or whether you just ignore it.)
I guess I will try an approach like the one Ben posted for now, just to find out how many patterns turn up.
Later I'd be interested in an elegant way to pre-test "parse-ability", though I have a healthy respect for the effort involved.
(And you've done a great job, I think, of keeping just what is needed and hiding lots of details in the "private" sections. One doesn't want to add more than is needed.)
(parameterize ([current-locale "en"])
(check-equal?
(parse-datetime "Sun, 21 Jun 2015 17:50:44 -0500 (CDT)" "EEE, dd MMM yyyy HH:mm:ss xxxx (zzzz)") (datetime 2015 6 21 17 50 44)))
that fails with
../../../../../Library/Racket/7.6/pkgs/gregor-lib/gregor/private/pattern/ast/zone.rkt:40:2: match: no matching clause for (Zone ... 'offset-name 'long)
I'm looking at the source code but am not quite sure. Are zone descriptors such as CDT supported? (I also tried (zzz), but it also fails with
no matching clause for (Zone ... 'offset-name 'short).)
In
https://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns
I find an example:
Pattern Result (in a particular locale)
yyyy.MM.dd G 'at' HH:mm:ss zzz 1996.07.10 AD at 15:08:56 PDT
which makes me think it should perhaps work.
OK, good to know. Maybe I can add the ones I need (if I can figure out how...). :)