Search code examples
javascriptvisual-studio-lightswitchdatetimeoffsetlightswitch-2013

Setting default DateTimeOffset in Javascript


Let's say I have an entity called 'Order', with a property called 'OrderDate'. In the save pipeline on the server I have validation logic like this:

partial void Orders_Validate(Order entity, EntitySetValidationResultsBuilder results) {
    if(entity.OrderDate > DateTime.Today)
             results.AddPropertyError(
                "Please specify a date that is not in the future",
                entity.Details.Properties.OrderDate);
}

To simplify data entry in the HTML client, when the user creates a new Order I want to set the OrderDate by default to today in the 'created' event of the entity, something like this:

myapp.Order.created = function (entity) {
    entity.OrderDate = new Date();
    entity.OrderDate.setHours(0, 0, 0, 0);
};

This works fine as long as the server and the client are in the same time zone.

Here are my three questions:

  1. Would this work also if the client is somewhere in east Asia where it's early morning on e.g. Monday but the server is in the US where it is still Sunday?
  2. What is the correct data type for the property 'OrderDate'? Should it be DateTimeOffset or would it work with just Date?
  3. If the type was DateTimeOffset, what is the correct way to set the 'OrderDate' property in javascript

Appreciate the help,

Best wishes


Solution

  • The following blog post, from the LightSwitch Team, provides some useful background regarding the best practice for dealing with different time zones:

    What Time Is It? Global Time (Steve Lasker)

    Based on this, you'd define your OrderDate field as a DateTimeOffset and default it on the JavaScript client as proposed e.g.:

    myapp.Order.created = function (entity) {
        entity.OrderDate = new Date();
        entity.OrderDate.setHours(0, 0, 0, 0);
    };
    

    Then, as you're using a DateTimeOffset, it should store the client value with the appropriate time zone offset, allowing you to implement the following type of approach in your validation:

    partial void Orders_Validate(Order entity, EntitySetValidationResultsBuilder results) {
        if (entity.OrderDate.Date > DateTimeOffset.Now.Date) {
            var languages = HttpContext.Current.Request.UserLanguages;
            // As the browser's language may not be set, 
            // the following falls back to the server's current culture info
            var ci = languages != null && languages.Length > 0 ? 
                new System.Globalization.CultureInfo(languages[0]) : 
                System.Globalization.CultureInfo.CurrentCulture;
            results.AddPropertyError(
                String.Format(
                    "The date {0} is invalid, please specify a date that is not in the future",
                    entity.OrderDate.ToLocalTime().Date.ToString("d", ci)),
                entity.Details.Properties.OrderDate);
        }
    }
    

    Just in case it's useful, the above example displays the validation message's date in the local time zone and culture specific short format, by using ToLocalTime and retrieving the user's browser language via their current HTTP request.