在简单的查询语言中,我想识别日期和时间文字,最好不使用分隔符。例如,
CreationDate = 2013-05-13 5:30 PM
我可以使用组合器来检测基本语法(例如,yyyy-MM-dd hh:mm tt
),但随后需要将其传递给以DateTime.TryParse
进行完全验证。
几个问题:
- 是否有用于“后处理”解析器结果的组合器,例如,
pstring "1/2/2000" |> (fun s -> try OK(DateTime.Parse s) with _ -> Fail("not a date"))
- 是否可以将谓词应用于字符串(就像
satisfy
to一样char
)? - 有没有更好的方法来解析日期/时间?
更新
使用 Guvante 和 Stephan 的例子,我想出了这个:
let dateTimeLiteral =
let date sep = pipe5 pint32 sep pint32 sep pint32 (fun a _ 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 a > 12 then a, b, c else c, a, b
let h, n =
match tt with
| Some((h, n), tt) ->
match tt with
| Some true -> (match h with 12 -> h | _ -> h + 12), n
| Some false -> (match h with 12 -> h - 12 | _ -> h), n
| None -> h, n
| None -> 0, 0
try preturn (System.DateTime(y, m, d, h, n, 0)) |>> DateTime
with _ -> fail "Invalid date/time format")