This project is read-only.

Handling Time zones properly

When the browser receives json data from the server it expects all dates are expressed in Utc format. Then it creates dates objects based on that Utc data, but that shows up in the browser local time. 

For a tutoral on Time zone handling in Asp.net Mvc please refer to: Asp.net Mvc and the nightmare of Dates and Time Zones. Below we will focus mainly on how Time zones are handled by the Mvc Controls Toolkit.

When dates are rendered on the server side in the Html page they shows up in the same time zone of the server. Coherently, also all minimum and maximum values possibly specified by validation attibutes are transferred to the client in the server local time, so everything takes place in the server local time.

When a model is transferred to the client automatically through the Client Blocks feature of the Mvc Controls Toolkit all dates contained there are automatuically converted into Utc format, so they will show in the local time of the browser. Also all minimum and maximum values possibly specified by validation attibutes are transformed into Utc format in a coherent way. If the client ViewModel is returned to the server by submitting the form it is contained in, then all dates are automatically transformed back into the local time of the server. Thus everything on the client takes place on the client local time and everything on the server takes place on the server local time.

When server-client communication takes place through json ajax calls dates are sent in Utc to the client but they are not transformed back to the server local time once they return back to the server. This means that all DateTimes received have a Kind property set to Utc. So a conversion might be needed.

The ControllerUtilities class contained in the MVCControlsToolkit.Controller namespace contains methods to both convert all DateTimes of an object into a different format or to set properly their Kind property. The last operation is necessary to enable a correct operation of all json serializers. In fact, in order to ensure that a Datetime is transformed into the Utc format formatters need to know if they are already in the Utc format:

 

DatesToLocale<T>(T x, bool round=false)

 

Transform all DateTimes contained in x (or in sub objects of x) into the local format. If rounded is true after the transformation the DateTimes are rounded to the nearest day.

 

public static void DatesToUTC<T>(T x, bool round=false)

 

Transform all DateTimes contained in x (or in sub objects of x) into the Utc format. If rounded is true after the transformation the DateTimes are rounded to the nearest day.

 

public static void DeclareAllDatesKind<T>(T x, DateTimeKind kind, bool round = false)

 

Changes the Kind of all DateTimes contained in x (or in sub objects of x). If rounded is true after the transformation the DateTimes are rounded to the nearest day.

 

public static void RoundDateTimesToDates<T>(T x)

 

Rounds all DateTimes contained in x (or in sub objects of x).

 

public static DateTime DeclareDateTimeKind (DateTime date, DateTimeKind kind)

 

Changes the Kind of date.

 

public static DateTime RoundDateTimeToDate(DateTime x)
public static DateTime? RoundDateTimeToDate(DateTime? x)

 

Round x  to the nearest day.

Rounding operations are important when dealing with date only fields whose time part is not processed on the client, as explained in the tutorial on Time zones.

Rounding on the client can be performed by the javascript function:

 

function MvcControlsToolkit_DateTimeToDate(date)

 

If data are retrieved by a retrievalManager the rounding operation can be performed in the dataTransform function has shown by the example below:

 

ClientToDoView.retrieval = mvcct.retrievalManager(query, ClientToDoView.DataPage.CurrPage, ClientToDoView.DataPage.TotalPages,
    {
        pageSize: 4,
        entitiesContainer: ClientToDoView.DataPage.ToDoList,
        updatesManager: ClientToDoView['updater'],
        jFormsToClear: $('#mainForm'),
        onError: function (args, x) {
            var exception = $.parseJSON(x.responseText);
            var message = mvcct.utils.isString(exception) ? exception : (exception.Message || "Internal Server Error");
            alert("status code: " + x.status + "; " + message);
        },
        dataTransform: function (x) {
            if (!x) return x;
            for (var i = 0; i < x.length; i++) {
                x[i].DueDate = mvcct.globalize.dateTimeToDate(x[i].DueDate); 
                //before 3.0.0: MvcControlsToolkit_DateTimeToDate(x[i].DueDate);
}
            return x;
        }
    });

 

If the some Kind change or DateTime format change operation needs to be performed on an IQueryable returned by a WebApi function we can use the action filter DateConversionFilterAttribute defined in the MVCControlsToolkit.ActionFilters namespace:

 

public enum DateConversionFilterOperation { ToUTC, ToLocale, DeclareUTC, DeclareLocale }
public DateConversionFilterAttribute(DateConversionFilterOperation operation)

 

Below an example of usage:

 

[DateConversionFilter(DateConversionFilterOperation.DeclareLocale), Queryable]
        public IQueryable<ToDoView> Get()
        {
            return ToDoViewModel.GetToDoQueryable();
        }

 

If in a Client Block a DateTime input control is enriched with the data-date-only="true" Html5 attribute, then that control will remember the Time part of the last value contained in the model property it is bound to and it will will use it as Time part of all input received by the user. This avoid the problems caused by truncations discussed in  the tutorial on Time zones

Last edited Jun 22, 2014 at 11:31 AM by frankabbruzzese, version 6

Comments

No comments yet.