RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.78k stars 1.29k forks source link

DateTime (de-)serialization in different Clients with C# DateTime.MinValue (or values before 1900 depending on timezones) #2694

Open kahmannf opened 4 years ago

kahmannf commented 4 years ago

NSwag toolchain v13.2.2.0

Certain DateTime values are deserialized differently by the C# and and the Typescript client depending on local Timezones.

TL;DR; Is there a way to provide a custom implementation for the (de-)serialization of Date-object in the Typescript-client? If so we could solve our problem ourselfs with a somewhat hacky work-around.

If not, here is our problem: Due to a difference in the specification of ECMAScript-Date and C#-DateTime, the serialization of certain date-values seems to be off in JS.

This is due to the fact that different timezones have been changed in the past. ECMAScript-Spec expect the browser to adjust this to the local time when creating Date-instances.

For example, Berlin, Germary (my timezone), used to be UTC+00:53:28h before April 1893, when it changed to UTC+1h.

Which causes the following output:

new Date("1893-04-01T00:00:00+01:00") => Fri Mar 31 1893 23:53:28 GMT+0053
new Date("1893-04-01T01:00:00+01:00") => Sat Apr 01 1893 01:00:00 GMT+0100

Note that the browser adapts the local timezone that was active at that time, generating an offset of 6:32 min, which will be mirrored in any inputs/displaying of the date.

We have an ASP.NETCore WebApi and two clients generated by NSwag, one C# (Silverlight) and one Typescript (Angular). We are currently migrating towards the Angular-client.

During migration we will have to support both clients, displaying the same Date-values in both application. The Silverlight-Runtime does not change the UTC Offset to UTC+00:53:28h and displays the expected date. We are using C#'s-DateTime.MinValue across our backend-achitecture and we unfortunatly can not refactor that. This value apparently uses local time, so our min-value is actually "0001-01-01T00:00:00+01:00" We also use the date "0001-01-01" to store time of day values (like 7:30 am), if they are not connected to a certain date, also in our local timezone ("0001-01-01T07:30:00+01:00"). These are displayed with a 6:32min offset and cannot be edited correctly.

I am (at least now) aware that using C#'s DateTime.MinValue may be bad design, but there is no way to change this right now.

Is it possible to teach the typescript client to deserialize "0001-01-01T00:00:00+01:00" to Mon Jan 01 0001 00:00:00 GMT+0053 (which would be like "0001-01-01T00:06:32+01:00") and serialize it back to "0001-01-01T00:00:00+01:00" (or UTC "0000-12-31T23:00:00.000Z")?

We can provide a typescript implementation for that if there is a possibility to provide a custom implementation for Date-parsing.

Of course it would be ideal if we could just toggle something like a "override historic timezone"-feature.

knoepdan commented 2 years ago

Maybe it should be possible to adapt the javascript to json serialization in the typescript client. Instead of

const content_ = JSON.stringify(input);

we should have something:

const content = customSerializer ? customSerializer.stringify(input) : JSON.stringify(input)

The customSerializer could be injected in the constructor, analogous to http and baseUrl. However, this would need some small changes to the code.