-
Notifications
You must be signed in to change notification settings - Fork 285
Description
When a .xsd file is used to create the XML TypeProvider type from a .xsd and when the .xsd uses xs:dateTime then if when the date is parsed into a DateTime structure it does not set the DateTime.Kind to something other than DateTimeKind.Unspecified an error will be raised when attempting to read the date value.
For example: given the following xsd fragment
<xs:element name="XMLTimeStamp" type="xs:dateTime" id="S1.2">
<xs:annotation>
<xs:documentation>Date and time that the XML was originally created.</xs:documentation>
</xs:annotation>
</xs:element>
and the following xml
<XMLTimeStamp>2022-04-28T10:09:17</XMLTimeStamp>
the following error is generated when trying to access the XMLTimeStamp
Installed Packages
Fsharp.Data, 4.2.8
Error: System.Exception: Expecting DateTimeOffset in Value, got 2022-04-28T10:09:17
at Microsoft.FSharp.Core.PrintfModule.PrintFormatToStringThenFail@1439.Invoke(String message) in D:\workspace\_work\1\s\src\fsharp\FSharp.Core\printf.fs:line 1439
at System.Runtime.CompilerServices.RuntimeHelpers.DispatchTailCalls(IntPtr callersRetAddrSlot, IntPtr callTarget, IntPtr retVal)
at FSharp.Data.Runtime.TextRuntime.GetNonOptionalValue[T](String name, FSharpOption`1 opt, FSharpOption`1 originalValue)
at <StartupCode$FSI_0029>.$FSI_0029.main@()
The issue is the code in AsDateTimeOffset in FileConversions.fs
match ParseISO8601FormattedDateTime text cultureInfo with
| Some d when d.Kind <> DateTimeKind.Unspecified ->
match DateTimeOffset.TryParse(text, cultureInfo, dateTimeStyles) with
| true, dto -> dto |> Some
| false, _ -> None
| _ -> None
When the date is 2022-04-28T10:09:17 them d.Kind is set to DateTimeKind.Unspecified when parsed into a DateTime by ParseISO8601FormattedDateTime and the code returns None. Changing the date 2022-04-28T10:09:17Z causes the d.Kind to be set and the date gets returned correctly.
One possible solution would be to mimic what AsDateTime, which is used when type=xs:date, does which is to give the DateTime the DateTimeKind.Local Kind when none is specified. This would change the code to something like this:
match ParseISO8601FormattedDateTime text cultureInfo with
| Some d when d.Kind = DateTimeKind.Unspecified ->
new DateTimeOffset(new DateTime(d.Ticks,DateTimeKind.Local)) |> Some
| Some d -> new DateTimeOffset(d) |> Some
| _ -> None
This also removes the double parsing of the date string that currently takes place.
An alternative and even simpler approach would be to ignore the fact that DateTimeKind.Unspecified is used, we still have a valid date and can construct a valid DateTimeOffset from it.
match ParseISO8601FormattedDateTime text cultureInfo with
| Some d -> new DateTimeOffset(d) |> Some
| _ -> None