ISO 8601 Date JS Interpretation Difference – IE/FF versus Chrome

Why do IE/FF and Chrome javascript engines differ on how to interpret this Date format (YYYY-MM-DDTHH:mm:ss.fff) without the timezone designator?

new Date("2015-02-18T15:43:57.803").getUTCHours()

UTC Hours

Chrome: 15

IE11/FF: 21

  • How do you return status 401 from WebAPI to AngularJS and also include a custom message?
  • Error “CommentsController does not have a default constructor”
  • Passing List of KeyValuePair or IDictionary to Web Api Controller from Javascript
  • How to check if a file download is complete in Web API
  • Generating a JS-client based on a ASP.NET WebAPI Controller
  • Asp.NET Web API and SignalR Cors
  • I don’t understand this – is it because Chrome assumes it’s local whereas IE/FF assume it’s UTC? This seems like a Chrome bug.

    Interestingly – appending a “Z” to the end of the string tells both Chrome and IE/FF that the time is UTC and they can agree. Has anyone else noticed this javascript implementation discrepancy with Date?

    new Date("2015-02-18T15:43:57.803Z").getUTCHours()
    

    UTC Hours

    Chrome: 15

    IE11/FF: 15

    Ultimately – this is the result of the out-of-box serializer for ASP.NET Web API, which I thought used JSON.NET, but now appears to be internal where JSON.NET uses IsoDateTimeConverter.

    Checking GlobalConfiguration.Configuration.Formatters.JsonFormatter tells me we’re using JsonMediaTypeFormatter. Is Web API not using JSON.NET serializer out of the box?

    This is a boon for Web API people – at least back in ASP.NET MVC we had a consistent date format (albeit proprietary – /Date(number of ticks)/) via the JavascriptSerializer

  • AngularJS $http get to ASP.NET Web Api with object in parameters
  • How to pass json POST data to Web API method as object
  • Image upload with Knockout and webapi c#
  • AngularJS + Web API - How to securely download an excel file without having to log in again
  • How to download binary file using ASP.net Web API and Javascript?
  • AngularJS $http.post to ASP.NET Web API controller with simple type argument
  • 2 Solutions collect form web for “ISO 8601 Date JS Interpretation Difference – IE/FF versus Chrome”

    ES5 says that ISO 8601 format dates without a time zone should be treated as local(that interpretation has since been revised), but the ed. 6 draft says to treat them as UTC. Some script engines have implemented ed. 6, some ES5 and the rest neither.

    The ed. 6 (and later) aren’t consistent with the ISO 8601 specification.

    The bottom line is don’t use Date.parse (or pass strings to the Date constructor), manually parse date strings.

    For us, the crux of this issue is that DateTimeStyles.RoundtripKind only works if your DateTime properties set the DateTime.DateTimeKind (other than DateTimeKind.Unspecified – the default) or better yet – using DateTimeOffset which enforces use of the TimeZone specificity.

    Since we already had DateTime class properties, we worked around this for now by assigning the JsonSerializerSettings.DateTimeZoneHandling from DateTimeZoneHandling.RoundtripKind (DateTime default) to DateTimeZoneHandling.Utc in our Global.asax.cs. This change essentially appends the “Z” to the end of the DateTime – however there is one more step to convert the Local time to UTC.

    The second step is to provide the offset by assigning IsoDateTimeConverter.DateTimeStyles which JSON.NET JsonSerializer will pickup from a SerializerSettings.Converters and automatically convert from Local time to UTC – much like the out-of-the-box ASP.NET MVC does.

    Obviously – there are other options, but this is solution worked for us.

    Global.asax.cs

    protected void Application_Start() {
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new IsoDateTimeConverter() { DateTimeStyles = DateTimeStyles.AdjustToUniversal });
    }
    

    The reason this works is because RoundtripKind honors DateTime’s DateTimeKind – which is Unspecified by default. We want to explicitly convert this to UTC – which JavaScriptSerializer used to do for us out of the box for ASP.NET MVC. The regional offset is provided by DateTimeStyles.AdjustToUniversal which converts your Local DateTime to UTC.