0

I have a piece of code that is giving me an unexpected output when taking a json date parameter. (this has been noticed as the software is being used in a different timezone to the one it was created in)

the html is a basic jquery datepicker field, so nothing wrong with that. I am just trying to match the date selected with a date in the database.

the JSON datetime that goes into the WebMethod FindDuplicates is in the correct format

2015-09-17T00:00:00.000Z

the javascript that calls the webservice is simply:

findDuplicates : function(options, success, error) {
    if(''+options.name == '' && ''+options.dateToCompare == '') {
        success&&success([], 'success', null);
        return;
    }
    return $software.__call_ajaxws('/webservices/FindDuplicates', { nameToMatch: options.name || null, dateToCompare: options.dateToCompare }, null, success || void (0), error || void (0), { elContent: 'Searching for duplicate records' });
}

in this (the none working) code, the variable dateToCompare

<WebMethod(), ScriptMethod(ResponseFormat:=ResponseFormat.Json), PrincipalPermission(SecurityAction.Demand, Authenticated:=True)> _
Public Function FindDuplicates(ByVal nameToMatch As String, ByVal dateToCompare As Nullable(Of DateTime))
    Dim someValue as String = "Foo"

at the point Dim someValue as String = "Foo" the value of dateToCompare has become 2015-09-17 09:00:00

whereas if I change the type of dateToCompare to a string it shows correctly as 2015-09-17 00:00:00

for some reason i cant work out, when casting/converting the parameter to a DateTime it decides to add the timezone of the server to the date, thereby sending an incorrect date to the comparison function meaning that a DB stored value of 2015-09-17 00:00:00 wont ever compare because it is being compared with 2015-09-17 09:00:00

is there someway I can stop the conversion process of string to datetime adding the timezone of the server?

kolin
  • 2,326
  • 1
  • 28
  • 46
  • @varocarbas at the first line within the function FindDuplicates dateToCompare has already had it's timezone added to it when it became cast as a type DateTime – kolin Sep 17 '15 at 08:39
  • If you're using ASP.NET AJAX in .NET 3.5, I think the JSON serializer being used automatically is `JavaScriptSerializer`, not Json.NET. Source: http://techblog.dorogin.com/2012/05/json-serializers-in-aspnet-and-other.html. How are you configuring / setting up your JSON serializer? – dbc Sep 17 '15 at 08:53
  • You should specify the conditions of the corresponding conversion to `DateTime` (via serialiser, as suggested by dbc, or by any other means). I deleted my previous comments because of not being completely sure about its actual applicability here. In any case the provided code (i.e., just including `dateToCompare As Nullable(Of DateTime)` and the input string) is not enough to understand the problem. A conversion from string to `DateTime` has to be performed (in a really bad scenario, it might be performed implicitely via `Option Strict Off`) and this part should be highlighted. – varocarbas Sep 17 '15 at 09:58

1 Answers1

0

The issue is that you appear to be using ASP.NET AJAX in .NET 3.5, and this actually uses JavaScriptSerializer to deserialize method arguments, according to the article Json serializers in ASP.NET and other. Thus your DateTime is not being deserialized for you by Json.NET, it's being deserialized for you by JavaScriptSerializer

And it appears that JavaScriptSerializer has bugs with correctly deserializing timezones of DateTime structs, according to JavaScriptSerializer UTC DateTime issues. That question further suggests a workaround: declare your argument as a DateTimeOffset, and then extract the time with UtcDateTime property.

Public Function FindDuplicates(ByVal nameToMatch As String, ByVal dateToCompare As Nullable(Of DateTimeOffset))
    Dim actualDateToCompare as Nullable(Of DateTime)
    if dateToCompare Is Nothing Then
        actualDateToCompare = Nothing
    else
        actualDateToCompare = dateToCompare.Value.UtcDateTime
    End If

A simple test case (in c#) seems to show that this fixes the problem:

        var jsonString = @"""2015-09-17T00:00:00.000Z""";

        var ok1 = (Newtonsoft.Json.JsonConvert.DeserializeObject<DateTime>(jsonString) == new JavaScriptSerializer().Deserialize<DateTimeOffset>(jsonString).UtcDateTime);
        Debug.Assert(ok1); // No assert

        var ok2 = (Newtonsoft.Json.JsonConvert.DeserializeObject<DateTime>(jsonString) == new JavaScriptSerializer().Deserialize<DateTime>(jsonString));
        Debug.Assert(ok2); // Assert FAILS
dbc
  • 104,963
  • 20
  • 228
  • 340