Skip to content

Reading a DateTime fails when the DateTime.Kind property gets set to Unspecified #1437

@rjmccann101

Description

@rjmccann101

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions