Как разобрать даты и опционные даты? - PullRequest
0 голосов
/ 10 апреля 2020

Когда я перебираю строки, возвращаемые 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()

Ответы [ 2 ]

0 голосов
/ 15 апреля 2020

Поставщик CSV пытается определить тип столбцов и выводит их как даты или необязательные даты. В вашем случае кажется, что вы просто хотите получить строковое значение, как оно есть в CSV-файле.

Вы можете легко получить это, указав Schema в поставщике типа CSV и переопределив поведение по умолчанию для столбцы даты, так что он просто дает вам строку.

Учитывая следующий CSV-файл, сохраненный как C:/temp/b.csv:

Site,OrderNumber,OrderDate,DeliveryDate
xyz,100,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,

Вы можете получить данные в нужном формате, используя:

type B = CsvProvider<"c:/temp/b.csv",Schema=",,string,string">

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

[ for r in B.GetSample().Rows ->
    { orderNumber = r.OrderNumber; 
      orderDate = r.OrderDate; 
      deliveryDate = r.DeliveryDate } ]
0 голосов
/ 14 апреля 2020

Как правило, это принимает форму развертки - где вы извлекаете внутренние значения из усиленного типа.

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

У нас нет никаких полиморфных c ограничений, которые позволили бы нам express тип как DateTime | DateTime option, поэтому нам просто нужно go с объектом.

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) = "")

PS

Вывод поставщика типа может быть fr agile, если у вас нет хорошей схемы или образца.

CsvProvider имеет опцию - InferRows. Это число строк, которые провайдер сканирует для создания схемы, и его значение по умолчанию составляет 1000.

Если вы хотите использовать все доступные строки образца:

type OrderProvider = CsvProvider<uri, InferRows = 0>
...