HtmlProvider 解析 Fraction As DateTime

HtmlProvider parses Fraction As DateTime

使用 HtmlProvider 访问基于 Web 的 table 有时 returns 作为字符串的分数(正确),在其他时候,returns DateTime(不正确)。 我错过了什么?

module Test = 

open FSharp.Data

let [<Literal>] url = "https://www.example.com/fractions"
type profile = HtmlProvider<url>    
let profile = profile.Load(url)

let [<Literal>] resultFile = @"C:\temp\data\Profile.csv" 

let CsvResult = 
    do
        use writer = new StreamWriter(resultFile, false)
        writer.WriteLine "\"Date\";\"Fraction\""
        for row in profile.Tables.Table1.Rows do
            "\"" + row.``Date``.ToString() + "\"" + ";" |> writer.Write
            "\"" + row.``Fraction``.ToString() + "\"" + ";" |> writer.WriteLine

        writer.Close

let csvResult = CsvResult

如果没有看到示例数据,我无法 100% 确定,但我猜测如果涉及的数字是您正在使用的文化中的有效日期,它会将分数解析为日期:例如,1/4 在使用 / 作为分隔符的任何文化中都是有效日期,并且将被视为 4 月 1 日或 1 月 4 日,具体取决于系统默认的解析文化。

FSharp.Data 中的其他类型提供程序(例如您可以使用的 CSV 类型提供程序)允许您配置每列的解析方式,但这不是 HTML 类型提供程序提供的选项。 (当然,这是一个缺少的功能)。但是由于 HTML 类型提供程序确实允许您为日期时间和数字解析指定区域性信息,因此您可以解决此问题的一种方法是指定一种区域性 not 使用 / 作为分隔符(但仍然使用 . 作为小数点,否则如果你正在解析的 HTML 的数字写成 1,000 表示一千,可以解释为 1)。一种这样的文化是 en-IN 文化 ("English (India)"),其中日期分隔符是 -,小数点是 ..

因此,请尝试在 HtmlProvider 选项中传递 Culture=System.Globalization.CultureInfo.GetCultureInfo("en-IN"),看看这是否有助于它停止将分数视为日期。

以下功能组合有效:

// http://www.fssnip.net/29/title/Regular-expression-active-pattern
module Solution = 

   open System
   open System.Text.RegularExpressions

   open FSharp.Data

   let (|Regex|_|) pattern input =
      let m = Regex.Match(input, pattern)
      if m.Success then Some(List.tail [ for g in m.Groups -> g.Value ])
      else None

   let ptrnFraction = @"^([0-9]?[0-9]?)(\/)([0-9]?[0-9]?)$"
   let ptrnDateTime = @"(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2}):(\d{2})"

   let ToFraction input = 
      match input with
      | Regex ptrnFraction [ numerator; operator; denominator ] ->
        (numerator + operator + denominator).ToString()
      | Regex ptrnDateTime [ day; month; year; hours; minutes; seconds ] ->
        (day + "/" + month).ToString()
      | _ -> "Not valid!"

   let dtInput = @"05/09/2017 00:00:00"
   let frcInput = @"13/20"

   let outDate = ToFraction dtInput
   printfn "Out Date: %s" outDate

   let outFraction = ToFraction frcInput
   printfn "Out Fraction: %s" outFraction

   //Output:> Out Date: 05/09 Out Fraction: 13/20

因此,我能够替换:

"\"" + row.``Fraction``.ToString() + "\"" + ";" |> writer.WriteLine

与:

"\"" + ToFraction(row.``Fraction``.ToString()) + "\"" + ";" |> writer.Write

感谢@rmunn 清晰的解释和他的专业知识。