datetime - Parsing date and time with FParsec -
within simple query language i'd recognize date , time literals, preferably without using delimiters. example,
creationdate = 2013-05-13 5:30 pm
i use combinator detect basic syntax (e.g., yyyy-mm-dd hh:mm tt
), needs passed datetime.tryparse
full validation.
a few questions:
- is there combinator "post processing" parser result, e.g.,
pstring "1/2/2000" |> (fun s -> try ok(datetime.parse s) _ -> fail("not date"))
- is possible apply predicate string (as
satisfy
char
)? - is there better approach parsing date/time?
update
using guvante's , stephan's examples, came this:
let datetimeliteral = let date sep = pipe5 pint32 sep pint32 sep pint32 (fun _ b _ c -> a, b, c) let time = (pint32 .>>. (skipchar ':' >>. pint32)) .>>. (opt (stringcireturn " am" false <|> stringcireturn " pm" true)) (date (pstring "/") <|> date (pstring "-")) .>>. (opt (skipchar ' ' >>. time)) .>> ws >>=? (fun ((a, b, c), tt) -> let y, m, d = if > 12 a, b, c else c, a, b let h, n = match tt | some((h, n), tt) -> match tt | true -> (match h 12 -> h | _ -> h + 12), n | false -> (match h 12 -> h - 12 | _ -> h), n | none -> h, n | none -> 0, 0 try preturn (system.datetime(y, m, d, h, n, 0)) |>> datetime _ -> fail "invalid date/time format")
you can build custom combinator or parser validates parsed input.
if want use combinators ("haskell-style"), use
let pdatestring = pstring "1/2/2000" let pdate1 = pdatestring >>= fun str -> try preturn (system.datetime.parse(str)) _ -> fail "date format error"
as guvante proposed.
if want avoid construction temporary parsers (see preturn ...
, pfail ...
above), can let function accept second parameter , directly return reply
values:
let pdate2 = pdatestring >>= fun str stream -> try reply(system.datetime.parse(str)) _ -> reply(error, messageerror "date format error")
if want error location @ beginning of malformed date string, replace >>=
>>=?
. note has consequences error recovery.
if want have full control, can write parser using lower level api, starting basic version following:
let pdate3 = fun stream -> let reply = pdatestring stream if reply.status = ok try reply(system.datetime.parse(reply.result)) _ -> reply(error, messageerror "date format error") else reply(reply.status, reply.error)
this last version allow replace pdatestring parser code directly accesses charstream interface, give additional flexibility or performance.
Comments
Post a Comment