gpt4 book ai didi

使用 FParsec 解析日期和时间

转载 作者:行者123 更新时间:2023-12-04 18:44:58 25 4
gpt4 key购买 nike

在简单的查询语言中,我想识别日期和时间文字,最好不使用分隔符。例如,

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"))
  • 是否可以将谓词应用于字符串(如 satisfychar 的作用)?
  • 有没有更好的方法来解析日期/时间?

  • 更新

    使用 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")

    最佳答案

    Is there a combinator for "post processing" a parser result



    如果你失败了,这取决于你想做什么。您可以随时做 |>>获取您的 DateTime出去。失败同样有趣,我认为你的例子可能是(给定一个解析器 sp 得到正确的字符串,注意它的类型是 Parser<string,'u> )
    sp >>= (fun s -> match DateTime.TryParse s with
    | true,result -> preturn result
    | false,_ -> fail)

    在这里,我接收结果字符串并调用 TryParse方法,并返回 preturnfail取决于它是否成功。我找不到任何完全像那样工作的方法。

    请注意 >>=?如果失败会导致回溯。

    Is it possible to apply a predicate to a string (as satisfy does for char)?



    您必须为每个字符( 220201 )调用谓词,这通常并不理想。我很确定如果你愿意,你可以做出这样的事情,但我认为这不是理想的原因,更不用说处理部分匹配变得更加困难。

    Is there a better approach for parsing date/time?



    最大的因素是“您对日期/时间了解多少?”如果您确切地知道它在该语法中,那么您应该能够使用后期处理并且很好(因为希望错误情况很少见)

    如果您不确定,例如如果 PM是可选的,但会明确详细,然后您可能希望分解定义并在最后组合它。注意这里我放宽了字符数,你可以添加一些 opt为了更加放松,或更换 pint32digit和手动转换。
    let pipe6 = //Implementation left as an exercise
    let dash = skipChar '-'
    let space = skipChar ' '
    let colon = skipChar ':'
    pipe6 (pint32 .>> dash) //Year
    (pint32 .>> dash) //Month
    (pint32 .>> space) //Day
    (pint32 .>> colon) //Hour
    (pint32 .>> space) //Minute
    (anyString) //AM/PM
    (fun year month day hour minute amPm ->
    DateTime(year, month, day,
    hour + (if amPm.Equals("PM", StringComparison.InvariantCultureIgnoreCase)
    then 12 else 0),
    minute, 0)) //No seconds

    把所有这些都写出来,我不确定你的情况是更好还是更糟......

    关于使用 FParsec 解析日期和时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16530466/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com