首页 > 解决方案 > 如何解析日期和选项日期?

问题描述

当我遍历由返回的行时,CSVProvider有些情况下日期要么包装在选项中,要么未包装。以下是数据的抽样:

+======+==============+============+===============+
| Site | Order Number | Order Date | Delivery Date |
+======+==============+============+===============+
| xyz  |          100 | 12/14/2019 | 3/16/2020     |
+------+--------------+------------+---------------+
| xyz  |          101 | 12/14/2019 | 3/16/2020     |
+------+--------------+------------+---------------+
| xyz  |          102 | 12/14/2019 | 3/16/2020     |
+------+--------------+------------+---------------+
| xyz  |          103 | 3/25/2020  |               |
+------+--------------+------------+---------------+
| xyz  |          104 | 3/26/2020  |               |
+------+--------------+------------+---------------+
| xyz  |          105 | 3/31/2020  | 4/5/2020      |
+------+--------------+------------+---------------+
| xyz  |          106 | 4/4/2020   |               |
+------+--------------+------------+---------------+
| xyz  |          107 | 4/10/2020  |               |
+------+--------------+------------+---------------+
| xyz  |          108 | 4/12/2020  |               |
+------+--------------+------------+---------------+

我想解析这些日期并构建具有日期字符串(当提供日期时)和空字符串的记录。

type example = { orderNumber: int; orderDate: string; deliveryDate: string }

我怎样才能实现上述目标?我想到并尝试了(参见下面的代码),构建一个自定义类型,为包装和未包装的 DateTimes 加上别名,然后根据需要提取/转换。

注意:下面包含的代码是非功能性的:

type DateTimeOption<DateTime> =
    | Some of DateTime
    | DateTime
    | None

let parseDate (date: DateTimeOption) =
    match date with
    | Some d -> d.ToString()
    | None -> ""
    | d: DateTime -> d.ToString()

标签: f#type-providers

解决方案


通常,这采用展开的形式 - 您从放大的类型中提取内部值。

unwrap: (T | A<T>) -> T

我们没有任何多态约束可以让我们将类型表示为DateTime | DateTime option,所以我们只需要使用 object。

let rec dateUnwrap (opt: obj) = 
    match opt with
    | :? DateTime as dt -> string dt
    | :? Option<DateTime> as opt -> 
        opt |> Option.map(dateUnwrap) |> Option.defaultValue ""
    | _ -> ""

测试

let now = DateTime.Now
assert ((dateUnwrap (Some now)) = string now)
assert ((dateUnwrap now) = string now)
assert ((dateUnwrap None) = "")

附言

如果您没有良好的架构或示例,类型提供程序推断可能很脆弱。

CsvProvider有选项 - InferRows。这是提供者为了构建模式而扫描的行数——它的默认值恰好是 1000。

如果要使用示例的所有可用行:

type OrderProvider = CsvProvider<uri, InferRows = 0>

推荐阅读