Skip to content

Commit 787cbac

Browse files
committed
make optional
1 parent 82b2baf commit 787cbac

10 files changed

Lines changed: 58 additions & 51 deletions

File tree

docs/library/CsvProvider.fsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ The following sample calls the `Load` method with an URL that points to a live C
8989
let msft = Stocks.Load(__SOURCE_DIRECTORY__ + "/../data/MSFT.csv").Cache()
9090

9191
// Look at the most recent row. Note the 'Date' property
92-
// is of type 'DateOnly' (on .NET 6+) or 'DateTime' (on older targets)
92+
// is of type 'DateTime' by default. Set PreferDateOnly = true
93+
// to use 'DateOnly' on .NET 6+
9394
// and 'Open' has a type 'decimal'
9495
let firstRow = msft.Rows |> Seq.head
9596
let lastDate = firstRow.Date
@@ -108,9 +109,9 @@ collection of rows. We iterate over the rows using a `for` loop. As you can see
108109
to the columns in the CSV file.
109110
110111
As you can see, the type provider also infers types of individual rows. The `Date`
111-
property is inferred to be a `DateOnly` on .NET 6 and later (because the values in the sample
112-
file are date-only strings without a time component), or `DateTime` on older targets. HLOC
113-
prices are inferred as `decimal`.
112+
property is inferred as `DateTime` by default. When you set `PreferDateOnly = true`
113+
on .NET 6 and later, date-only strings (without a time component) are inferred as `DateOnly`.
114+
HLOC prices are inferred as `decimal`.
114115
115116
## Using units of measure
116117
@@ -271,10 +272,9 @@ it by specifying the `InferRows` static parameter of `CsvProvider`. If you speci
271272
Columns with only `0`, `1`, `Yes`, `No`, `True`, or `False` will be set to `bool`. Columns with numerical values
272273
will be set to either `int`, `int64`, `decimal`, or `float`, in that order of preference.
273274
274-
On .NET 6 and later, columns whose values are all date-only strings (without a time component, e.g. `2023-01-15`)
275-
are automatically inferred as `DateOnly`. If a column mixes `DateOnly` and `DateTime` values, it is unified to `DateTime`.
276-
Note that `TimeOnly` is **not** auto-inferred because it is ambiguous with `TimeSpan`; use an explicit schema annotation
277-
(see the list of valid types below) to get a `TimeOnly` column.
275+
On .NET 6 and later, when you set `PreferDateOnly = true`, columns whose values are all date-only strings (without a time component, e.g. `2023-01-15`)
276+
are inferred as `DateOnly`. Time-only strings are inferred as `TimeOnly`. If a column mixes `DateOnly` and `DateTime` values, it is unified to `DateTime`.
277+
By default (`PreferDateOnly = false`), all date values are inferred as `DateTime` for backward compatibility.
278278
279279
If a value is missing in any row, by default the CSV type provider will infer a nullable (for `int`, `int64`, and `DateOnly`) or an optional
280280
(for `bool`, `DateTime`, `DateTimeOffset`, and `Guid`). When a `decimal` would be inferred but there are missing values, we will infer a
@@ -388,19 +388,20 @@ You can even mix and match the two syntaxes like this `Schema="int64,DidSurvive,
388388
389389
### DateOnly and TimeOnly (on .NET 6+)
390390
391-
On .NET 6 and later, date-only strings are automatically inferred as `DateOnly`. For example, a column
392-
like `EventDate` containing values such as `2023-06-01` will be given the type `DateOnly`.
391+
On .NET 6 and later, when you set `PreferDateOnly = true`, date-only strings are inferred as `DateOnly`
392+
and time-only strings as `TimeOnly`. For example, a column like `EventDate` containing values such as
393+
`2023-06-01` will be given the type `DateOnly`. By default (`PreferDateOnly = false`), dates are
394+
inferred as `DateTime` for backward compatibility.
393395
394396
You can also explicitly request a `DateOnly` or `TimeOnly` column using schema annotations:
395397
396398
[lang=text]
397-
EventDate,Duration (timeonly?)
399+
EventDate (dateonly),Duration (timeonly?)
398400
2023-06-01,08:30:00
399401
2023-06-02,
400402
401-
In the example above, `EventDate` is auto-inferred as `DateOnly` and `Duration` is explicitly
402-
annotated as `timeonly?` (a nullable `TimeOnly`). Note that `TimeOnly` is never auto-inferred
403-
(to avoid confusion with `TimeSpan`), so the schema annotation is required to get a `TimeOnly` column.
403+
In the example above, `EventDate` is explicitly annotated as `dateonly` and `Duration` is explicitly
404+
annotated as `timeonly?` (a nullable `TimeOnly`).
404405
405406
## Transforming CSV files
406407

docs/library/JsonProvider.fsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,9 @@ process it dynamically as described in [the documentation for `JsonValue`](JsonV
122122
### Inferring date types
123123
124124
String values in JSON that look like dates are inferred as `DateTime` or `DateTimeOffset`.
125-
On .NET 6 and later, strings that represent a date without a time component (e.g. `"2023-01-15"`)
126-
are inferred as `DateOnly`. Full datetime strings (e.g. `"2023-01-15T10:30:00"`) continue to be
127-
inferred as `DateTime`.
125+
On .NET 6 and later, when you set `PreferDateOnly = true`, strings that represent a date without a time component (e.g. `"2023-01-15"`)
126+
are inferred as `DateOnly`, and time-only strings are inferred as `TimeOnly`. By default (`PreferDateOnly = false`),
127+
all dates are inferred as `DateTime` for backward compatibility.
128128
129129
### Inferring record types
130130

src/FSharp.Data.DesignTime/Csv/CsvProvider.fs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type public CsvProvider(cfg: TypeProviderConfig) as this =
5555
let encodingStr = args.[13] :?> string
5656
let resolutionFolder = args.[14] :?> string
5757
let resource = args.[15] :?> string
58+
let preferDateOnly = args.[16] :?> bool
5859

5960
// This provider already has a schema mechanism, so let's disable inline schemas.
6061
let inferenceMode = InferenceMode'.ValuesOnly
@@ -115,7 +116,7 @@ type public CsvProvider(cfg: TypeProviderConfig) as this =
115116
unitsOfMeasureProvider
116117
)
117118
#if NET6_0_OR_GREATER
118-
if ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
119+
if preferDateOnly && ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
119120
fields
120121
else
121122
fields |> List.map StructuralInference.downgradeNet6PrimitiveProperty
@@ -232,7 +233,8 @@ type public CsvProvider(cfg: TypeProviderConfig) as this =
232233
ProvidedStaticParameter("Culture", typeof<string>, parameterDefaultValue = "")
233234
ProvidedStaticParameter("Encoding", typeof<string>, parameterDefaultValue = "")
234235
ProvidedStaticParameter("ResolutionFolder", typeof<string>, parameterDefaultValue = "")
235-
ProvidedStaticParameter("EmbeddedResource", typeof<string>, parameterDefaultValue = "") ]
236+
ProvidedStaticParameter("EmbeddedResource", typeof<string>, parameterDefaultValue = "")
237+
ProvidedStaticParameter("PreferDateOnly", typeof<bool>, parameterDefaultValue = false) ]
236238

237239
let helpText =
238240
"""<summary>Typed representation of a CSV file.</summary>
@@ -255,7 +257,8 @@ type public CsvProvider(cfg: TypeProviderConfig) as this =
255257
<param name='Encoding'>The encoding used to read the sample. You can specify either the character set name or the codepage number. Defaults to UTF8 for files, and to ISO-8859-1 the for HTTP requests, unless <c>charset</c> is specified in the <c>Content-Type</c> response header.</param>
256258
<param name='ResolutionFolder'>A directory that is used when resolving relative file references (at design time and in hosted execution).</param>
257259
<param name='EmbeddedResource'>When specified, the type provider first attempts to load the sample from the specified resource
258-
(e.g. 'MyCompany.MyAssembly, resource_name.csv'). This is useful when exposing types generated by the type provider.</param>"""
260+
(e.g. 'MyCompany.MyAssembly, resource_name.csv'). This is useful when exposing types generated by the type provider.</param>
261+
<param name='PreferDateOnly'>When true on .NET 6+, date-only strings are inferred as DateOnly and time-only strings as TimeOnly. Defaults to false for backward compatibility.</param>"""
259262

260263
do csvProvTy.AddXmlDoc helpText
261264
do csvProvTy.DefineStaticParameters(parameters, buildTypes)

src/FSharp.Data.DesignTime/Html/HtmlProvider.fs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type public HtmlProvider(cfg: TypeProviderConfig) as this =
4141
let encodingStr = args.[5] :?> string
4242
let resolutionFolder = args.[6] :?> string
4343
let resource = args.[7] :?> string
44+
let preferDateOnly = args.[8] :?> bool
4445

4546
// Allowing inline schemas does not seem very valuable for this provider.
4647
// Let's stick to the default values for now.
@@ -63,7 +64,8 @@ type public HtmlProvider(cfg: TypeProviderConfig) as this =
6364
InferenceMode = inferenceMode }
6465

6566
#if NET6_0_OR_GREATER
66-
let supportsNet6Types = ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly
67+
let supportsNet6Types =
68+
preferDateOnly && ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly
6769
#else
6870
let supportsNet6Types = false
6971
#endif
@@ -97,7 +99,8 @@ type public HtmlProvider(cfg: TypeProviderConfig) as this =
9799
ProvidedStaticParameter("Culture", typeof<string>, parameterDefaultValue = "")
98100
ProvidedStaticParameter("Encoding", typeof<string>, parameterDefaultValue = "")
99101
ProvidedStaticParameter("ResolutionFolder", typeof<string>, parameterDefaultValue = "")
100-
ProvidedStaticParameter("EmbeddedResource", typeof<string>, parameterDefaultValue = "") ]
102+
ProvidedStaticParameter("EmbeddedResource", typeof<string>, parameterDefaultValue = "")
103+
ProvidedStaticParameter("PreferDateOnly", typeof<bool>, parameterDefaultValue = false) ]
101104

102105
let helpText =
103106
"""<summary>Typed representation of an HTML file.</summary>
@@ -112,6 +115,7 @@ type public HtmlProvider(cfg: TypeProviderConfig) as this =
112115
<param name='ResolutionFolder'>A directory that is used when resolving relative file references (at design time and in hosted execution).</param>
113116
<param name='EmbeddedResource'>When specified, the type provider first attempts to load the sample from the specified resource
114117
(e.g. 'MyCompany.MyAssembly, resource_name.html'). This is useful when exposing types generated by the type provider.</param>
118+
<param name='PreferDateOnly'>When true on .NET 6+, date-only strings are inferred as DateOnly and time-only strings as TimeOnly. Defaults to false for backward compatibility.</param>
115119
"""
116120

117121
do htmlProvTy.AddXmlDoc helpText

src/FSharp.Data.DesignTime/Json/JsonProvider.fs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
5757
let preferDictionaries = args.[8] :?> bool
5858
let inferenceMode = args.[9] :?> InferenceMode
5959
let schema = args.[10] :?> string
60+
let preferDateOnly = args.[11] :?> bool
6061

6162
let inferenceMode =
6263
InferenceMode'.FromPublicApi(inferenceMode, inferTypesFromValues)
@@ -100,7 +101,7 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
100101
JsonInference.inferType unitsOfMeasureProvider inferenceMode cultureInfo "" sampleJson)
101102
|> Array.fold (StructuralInference.subtypeInfered false) InferedType.Top
102103
#if NET6_0_OR_GREATER
103-
if ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
104+
if preferDateOnly && ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
104105
rawInfered
105106
else
106107
StructuralInference.downgradeNet6Types rawInfered
@@ -162,7 +163,8 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
162163
typeof<InferenceMode>,
163164
parameterDefaultValue = InferenceMode.BackwardCompatible
164165
)
165-
ProvidedStaticParameter("Schema", typeof<string>, parameterDefaultValue = "") ]
166+
ProvidedStaticParameter("Schema", typeof<string>, parameterDefaultValue = "")
167+
ProvidedStaticParameter("PreferDateOnly", typeof<bool>, parameterDefaultValue = false) ]
166168

167169
let helpText =
168170
"""<summary>Typed representation of a JSON document.</summary>
@@ -185,7 +187,8 @@ type public JsonProvider(cfg: TypeProviderConfig) as this =
185187
| ValuesAndInlineSchemasHints -> Types of values are inferred from both values and inline schemas. Inline schemas are special string values that can define a type and/or unit of measure. Supported syntax: typeof&lt;type&gt; or typeof{type} or typeof&lt;type&lt;measure&gt;&gt; or typeof{type{measure}}. Valid measures are the default SI units, and valid types are <c>int</c>, <c>int64</c>, <c>bool</c>, <c>float</c>, <c>decimal</c>, <c>date</c>, <c>datetimeoffset</c>, <c>timespan</c>, <c>guid</c> and <c>string</c>.
186188
| ValuesAndInlineSchemasOverrides -> Same as ValuesAndInlineSchemasHints, but value inferred types are ignored when an inline schema is present.
187189
</param>
188-
<param name='Schema'>Location of a JSON Schema file or a string containing a JSON Schema document. When specified, Sample and SampleIsList must not be used.</param>"""
190+
<param name='Schema'>Location of a JSON Schema file or a string containing a JSON Schema document. When specified, Sample and SampleIsList must not be used.</param>
191+
<param name='PreferDateOnly'>When true on .NET 6+, date-only strings (e.g. "2023-01-15") are inferred as DateOnly and time-only strings as TimeOnly. Defaults to false for backward compatibility.</param>"""
189192

190193
do jsonProvTy.AddXmlDoc helpText
191194
do jsonProvTy.DefineStaticParameters(parameters, buildTypes)

src/FSharp.Data.DesignTime/Xml/XmlProvider.fs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type public XmlProvider(cfg: TypeProviderConfig) as this =
5050
let inferTypesFromValues = args.[7] :?> bool
5151
let schema = args.[8] :?> string
5252
let inferenceMode = args.[9] :?> InferenceMode
53+
let preferDateOnly = args.[10] :?> bool
5354

5455
let inferenceMode =
5556
InferenceMode'.FromPublicApi(inferenceMode, inferTypesFromValues)
@@ -77,7 +78,7 @@ type public XmlProvider(cfg: TypeProviderConfig) as this =
7778
let t =
7879
schemaSet |> XsdParsing.getElements |> List.ofSeq |> XsdInference.inferElements
7980
#if NET6_0_OR_GREATER
80-
if ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
81+
if preferDateOnly && ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
8182
t
8283
else
8384
StructuralInference.downgradeNet6Types t
@@ -132,7 +133,7 @@ type public XmlProvider(cfg: TypeProviderConfig) as this =
132133
globalInference
133134
|> Array.fold (StructuralInference.subtypeInfered false) InferedType.Top
134135
#if NET6_0_OR_GREATER
135-
if ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
136+
if preferDateOnly && ProviderHelpers.runtimeSupportsNet6Types cfg.RuntimeAssembly then
136137
t
137138
else
138139
StructuralInference.downgradeNet6Types t
@@ -193,7 +194,8 @@ type public XmlProvider(cfg: TypeProviderConfig) as this =
193194
"InferenceMode",
194195
typeof<InferenceMode>,
195196
parameterDefaultValue = InferenceMode.BackwardCompatible
196-
) ]
197+
)
198+
ProvidedStaticParameter("PreferDateOnly", typeof<bool>, parameterDefaultValue = false) ]
197199

198200
let helpText =
199201
"""<summary>Typed representation of a XML file.</summary>
@@ -216,7 +218,8 @@ type public XmlProvider(cfg: TypeProviderConfig) as this =
216218
| ValuesAndInlineSchemasHints -> Types of values are inferred from both values and inline schemas. Inline schemas are special string values that can define a type and/or unit of measure. Supported syntax: typeof&lt;type&gt; or typeof{type} or typeof&lt;type&lt;measure&gt;&gt; or typeof{type{measure}}. Valid measures are the default SI units, and valid types are <c>int</c>, <c>int64</c>, <c>bool</c>, <c>float</c>, <c>decimal</c>, <c>date</c>, <c>datetimeoffset</c>, <c>timespan</c>, <c>guid</c> and <c>string</c>.
217219
| ValuesAndInlineSchemasOverrides -> Same as ValuesAndInlineSchemasHints, but value inferred types are ignored when an inline schema is present.
218220
Note inline schemas are not used from Xsd documents.
219-
</param>"""
221+
</param>
222+
<param name='PreferDateOnly'>When true on .NET 6+, date-only strings are inferred as DateOnly and time-only strings as TimeOnly. Defaults to false for backward compatibility.</param>"""
220223

221224

222225
do xmlProvTy.AddXmlDoc helpText

tests/FSharp.Data.Tests/CsvProvider.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ let [<Literal>] csvWithGermanDate = """Preisregelung_ID;Messgebiet_Nr;gueltig_se
5151

5252
[<Test>]
5353
let ``Inference of german dates`` () =
54-
let csv = CsvProvider<csvWithGermanDate, ";", InferRows = 0, Culture = "de-DE">.GetSample()
54+
let csv = CsvProvider<csvWithGermanDate, ";", InferRows = 0, Culture = "de-DE", PreferDateOnly = true>.GetSample()
5555
let rows = csv.Rows |> Seq.toArray
5656

5757
let row = rows.[1]
@@ -67,7 +67,7 @@ Float1,Float2,Float3,Float4,Int,Float5,Float6,Date
6767

6868
[<Test>]
6969
let ``Inference of numbers with empty values`` () =
70-
let csv = CsvProvider<csvWithEmptyValues>.GetSample()
70+
let csv = CsvProvider<csvWithEmptyValues, PreferDateOnly = true>.GetSample()
7171
let rows = csv.Rows |> Seq.toArray
7272

7373
let row = rows.[0]
@@ -101,7 +101,7 @@ let [<Literal>] csvData = """DateOnly,DateWithOffset,MixedDate,OffsetOption (dat
101101

102102
[<Test>]
103103
let ``Can infer DateTime and DateTimeOffset types correctly`` () =
104-
let csv = CsvProvider<csvData, ",", InferRows = 0>.GetSample()
104+
let csv = CsvProvider<csvData, ",", InferRows = 0, PreferDateOnly = true>.GetSample()
105105
let firstRow = csv.Rows |> Seq.head
106106
let secondRow = csv.Rows |> Seq.item 1
107107

@@ -153,7 +153,7 @@ let ``Does not treat invariant culture number such as 3.14 as a date in cultures
153153
targetCulture.DateTimeFormat.DateSeparator |> should equal "."
154154
targetCulture.DateTimeFormat.TimeSeparator |> should equal ":" // See https://github.com/fsprojects/FSharp.Data/issues/767
155155
targetCulture.NumberFormat.NumberDecimalSeparator |> should equal ","
156-
let csv = CsvProvider<"Data/DnbHistoriskeKurser.csv", ",", 10, Culture=norwayCultureName>.GetSample()
156+
let csv = CsvProvider<"Data/DnbHistoriskeKurser.csv", ",", 10, Culture=norwayCultureName, PreferDateOnly = true>.GetSample()
157157
let row = csv.Rows |> Seq.head
158158
(row.Dato, row.USD) |> should equal (DateOnly(2013, 2, 7), "5.4970")
159159

tests/FSharp.Data.Tests/HtmlProviderList.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ let ``Simple List infers date type correctly ``() =
7373
<li>03/03/2013</li>
7474
</ul>
7575
</body>
76-
</html>""", PreferOptionals=true>.GetSample().Lists.List1
76+
</html>""", PreferOptionals=true, PreferDateOnly=true>.GetSample().Lists.List1
7777
list.Values |> should equal [|DateOnly(2013,1,1);DateOnly(2013,2,2);DateOnly(2013,3,3)|]
7878

7979
[<Test>]
@@ -144,7 +144,7 @@ let ``Handles simple definition list``() =
144144
<dd></dd>
145145
</dl>
146146
</body>
147-
</html>""", PreferOptionals=true>.GetSample().DefinitionLists.DefinitionList1
147+
</html>""", PreferOptionals=true, PreferDateOnly=true>.GetSample().DefinitionLists.DefinitionList1
148148
list.Count.Values |> should equal [|1;2|]
149149
list.Dates.Values |> should equal [|DateOnly(2014,1,1); DateOnly(2014, 2,2)|]
150150
list.Decimals.Values |> should equal [|1.23M; 2.23M|]

0 commit comments

Comments
 (0)