3

I am saving all dates in my database as UTC. I now need to adjust to the client's local timezone.

Some background. I am using WebApi2 and I have an ASP.Net MVC5 web app consuming it. Eventually native apps will also consume the WebApi2 service.

Here is the method I use to get and render

protected async Task<T> GetAndParseApiResponse<T>(string url)
{
    T model = default(T);

    using (HttpClient client = GetHttpClient(SessionWrapper.AuthToken))
    {
        try
        {
            var response = await client.GetAsync(url)
                .ConfigureAwait(false);

            var formatter = new JsonMediaTypeFormatter
            {
                SerializerSettings = { TypeNameHandling = TypeNameHandling.Auto }
            };

            model = await response.Content.ReadAsAsync<T>(new List<MediaTypeFormatter> { formatter })
                .ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            throw new Exception("An exception occured performing GET at " + url, ex);
        }
    }

Some of the options I have come across that I am not too keen on include:

  1. Convert at client size using moment and moment.timezone - I have tried this and it is unreliable because I had to use this code to compensate for DST which seems to work sometimes, and others it does not, so sometimes the time is correct times it is an hour forward, but in truth i'm not keen on handling it here so best I move on from this approach maybe:

    var tz = jstz.determine();
    var m = moment(value).tz(tz.name());
    return m.add(m.isDST() ? 1 : 0, 'hours');
    
  2. Manually adjust each DateTime object with the appropriate offset - Surely this is a last resort?! By this i mean every time a DateTime object is set to append the offset

  3. Customise the JSON serializer so that DateTime are converted silently when returning a response from WebApi2 (or when receiving it). The reason I "think" this global approach would be the best is because I have DateTime objects in a lot of different models and are all currently being rendered as UTC at the client (ASP.Net MVC application). I need to adjust this DateTime before it is passed down as it is curently being deserialized with the UTC date (right or wrong that is what is happening)

I would love to implement option 3. I already have the client's local timezone as an offset (01:00, 02:00 etc). I'm just a bit confused to how to custom the serializer and where to do it.

Any help is greatly appreciated

Ryan
  • 7,835
  • 2
  • 29
  • 36
pieperu
  • 2,662
  • 3
  • 18
  • 31
  • If you use DateTime objects, when serialized they include the timezone, they're serialized in the form of YYYY-DD-mmThh:mm:ss.mmmm+(offset) so the JavaScript object (or the other .net end point) will recognize it and use the time offset respect the user's settings – Gusman May 03 '16 at 14:29
  • My issue is that it is not, it is serializing as UTC because it has the "Z" at the end. And if it serializes automatically, how do i set the offset on a per user basis. I dont want the local time of the server, i want the local time of the client. – pieperu May 03 '16 at 15:04
  • When you deserialize the object as a Date JavaScript object the Date object will take care of the offset, if you send a date in UTC and the client is on +01:00 it will transform the date to the correct timezone, check this fiddle: https://jsfiddle.net/nefkamne/1/ – Gusman May 03 '16 at 15:10
  • A couple of questions: 1) You said you found moment-timezone to be unreliable. In what way exactly? 2) You said you already have the client's time zone. What specifically do you have? A Windows time zone ID? An IANA time zone ID? An offset from UTC? Something else? Give an example please. 3) When you say "Explicitly adjust each DateTime object with the appropriate offset", do you mean you are trying to add/subtract time? Or are you using `TimeZoneInfo` or [Noda Time](http://nodatime.org) already? – Matt Johnson-Pint May 03 '16 at 15:42
  • 1
    4) Why do you want to handle this globally as a serialization concern? It's usually better to think of it as an application logic concern. (`DateTimeOffset` is a useful type in modeling the output.). Consider how you might handle adding a feature down the road that needed the results in a different time zone. – Matt Johnson-Pint May 03 '16 at 15:42
  • Thanks for your input Matt. I updated the question with some more info. The WebApi RESTful service is being consumed by an ASP.Net MVC 5 Web app. For reasons that I wont go into, there are some pages that do request JSON, and these also go through the MVC app (bearer token is saved in session). I take your point about an application logic concern, so are you saying that I should handle this when the objects are deserialized at the client? and if so, is there a way to customize the deserializer so that it correctly formats dates with the correct offset? – pieperu May 04 '16 at 08:11
  • There should not be a feature that needs to return any date in any timezone other than the one the client is in, these are the dates that sporting events will happen. This is why it is stored in UTC everywhere so that it can be customised based on the client. – pieperu May 04 '16 at 08:17

0 Answers0