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 清晰的解释和他的专业知识。
使用 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 清晰的解释和他的专业知识。