Working with Controls / CollectionView / Work with CollectionView / DateTime Processing
DateTime Processing

This topic demonstrates how to keep a DateTime property in a UTC format on both server and client when using FlexGrid with Ajax Binding or Editing. To achieve this, we first need to understand how the DateTime values are processed at client side and server side.

On the Server side, every time you use the DateTime class, you need to specify the Kind property, which indicates whether the time represented by this instance is based on local time, Coordinated Universal Time (UTC), or neither. However, when you are working with DateTime object at the Client side, the browser implicitly convert all dates according to the local time when the date is parsed from a Number to Date object.

For example, when you create a DateTime instance on server side, such as new DateTime(2017, 0, 25, 7, 0, 0, DateTimeKind.Utc);. Once you transfer this value from server to client, browsers on different machines which use different TimeZone system settings show different string representations.

To keep time in the UTC format, you need to apply an explicit transformation to the dates on both client and server.

In case of server, you need to convert all the DateTime objects to Unspecified and, then convert them back when necessary using CREATE, UPDATE or DELETE operations. You need to implement the following two steps.

  1. Convert to Unspecified format during reading data.
  2. Convert Unspecified format back during CREATE, UPDATE and DELETE operations.

To understand the transformation, we will take an example of the FlexGrid control, which include DateTime fields with different formats, such as: Utc, Local and Unspecified. Bind the grid with these data values.

Create a new Model

  1. Add a new class to the folder Models (for example: DatesData.cs). For more information on how to add a new model, see Adding Controls.
  2. Replace the following code in the new model to define the classes that serve as a data source for the FlexGrid control.
    DatesData.cs
    Copy Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace DateTimeFields.Models
    {
        public class DatesData
        {
             
            // The primary key.
            public int Id { get; set; }
    
            // A DateTime field which Kind is Utc.
            public DateTime UtcDateTime { get; set; }
    
            // A DateTime field which Kind is Unspecified.
            public DateTime UnspecifiedDateTime { get; set; }
    
            // A DateTime field which Kind is Local.
            public DateTime LocalDateTime { get; set; }
            
            // Get the data.
            // <param name="total"></param>
            // <returns></returns>
            public static IEnumerable<DatesData> GetData(int total)
            {
                var rand = new Random(0);
                var dt = DateTime.Now;
                var list = Enumerable.Range(0, total).Select(i =>
                {
                   return new DatesData
                   {
                      Id = i + 1,
                      UtcDateTime =
                         new DateTime(dt.Year, i % 12 + 1, 25, 7, 0, 0, DateTimeKind.Utc),
                      UnspecifiedDateTime =
                         new DateTime(dt.Year, i % 12 + 1, 25, 7, 0, 0, DateTimeKind.Unspecified),
                      LocalDateTime =
                         new DateTime(dt.Year, i % 12 + 1, 25, 7, 0, 0, DateTimeKind.Local)
                    };
                });
    
                return list;
            }
        }
    }
    

Controller

In Code - HomeController.cs

C#
Copy Code
using C1.Web.Mvc;
using C1.Web.Mvc.Serialization;
using <ApplicationName>.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace DateTimeFields.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        private static List<DatesData> convertedData = DatesData.GetData(3).ToList();
        private static List<DatesData> ConvertToUnspecifiedData(IEnumerable<DatesData> sourceData)
        {
            return sourceData.Select(item => new DatesData
            {
                Id = item.Id,
                UnspecifiedDateTime = item.UnspecifiedDateTime,
                UtcDateTime = new DateTime(item.UtcDateTime.Ticks),
                LocalDateTime = new DateTime(item.LocalDateTime.Ticks)
            }).ToList();
        }

        private static void ConvertUpspecifiedBack(CollectionViewEditRequest<DatesData> requestData)
        {
           // Convert Unspecified DateTime back.
           foreach (var item in requestData.OperatingItems)
           {
              item.LocalDateTime = new DateTime(item.LocalDateTime.Ticks, DateTimeKind.Local);
              item.UtcDateTime = new DateTime(item.UtcDateTime.Ticks, DateTimeKind.Utc);
           }
        }
        public ActionResult Converted_ReadDatesData(
                     [C1JsonRequest] CollectionViewRequest<DatesData> requestData)
        {
            return this.C1Json(CollectionViewHelper.Read(requestData, 
                        ConvertToUnspecifiedData(convertedData)));
        }
        public ActionResult Converted_UpdateDatesData(
                     [C1JsonRequest]CollectionViewEditRequest<DatesData> requestData)
        {
            ConvertUpspecifiedBack(requestData);
            return Update(requestData, convertedData, ConvertToUnspecifiedData);
        }
        public ActionResult Converted_CreateDatesData(
                     [C1JsonRequest]CollectionViewEditRequest<DatesData> requestData)
        {
            ConvertUpspecifiedBack(requestData);
            return Create(requestData, convertedData, ConvertToUnspecifiedData);
        }
        public ActionResult Converted_DeleteDatesData(
                     [C1JsonRequest]CollectionViewEditRequest<DatesData> requestData)
        {
            ConvertUpspecifiedBack(requestData);
            return Delete(requestData, convertedData, ConvertToUnspecifiedData);
        }

        public ActionResult Update(CollectionViewEditRequest<DatesData> requestData,
                     List<DatesData> sourceData, Func<IEnumerable<DatesData>, 
                     List<DatesData>> converter = null)
        {
            return this.C1Json(CollectionViewHelper.Edit(requestData, item =>
            {
                var error = string.Empty;
                var success = true;
                try
                {
                    var index = sourceData.FindIndex(u => u.Id == item.Id);
                    sourceData.RemoveAt(index);
                    sourceData.Insert(index, item);
                }
                catch (Exception e)
                {
                    error = e.Message;
                    success = false;
                }
                return new CollectionViewItemResult<DatesData>
                {
                    Error = error,
                    Success = success,
                    Data = item
                };
            }, () => converter != null ? converter(sourceData) : sourceData));
        }

        public ActionResult Create(CollectionViewEditRequest<DatesData> requestData, 
                     List<DatesData> sourceData, Func<IEnumerable<DatesData>,
                     List<DatesData>> converter = null)
        {
            return this.C1Json(CollectionViewHelper.Edit(requestData, item =>
            {
                var error = string.Empty;
                var success = true;
                try
                {
                    sourceData.Add(item);
                    item.Id = sourceData.Max(u => u.Id) + 1;
                }
                catch (Exception e)
                {
                    error = e.Message;
                    success = false;
                }
                return new CollectionViewItemResult<DatesData>
                {
                    Error = error,
                    Success = success,
                    Data = item
                };
            }, () => converter != null ? converter(sourceData) : sourceData));
        }

        public ActionResult Delete(CollectionViewEditRequest<DatesData> requestData,
                     List<DatesData> sourceData, Func<IEnumerable<DatesData>,
                     List<DatesData>> converter = null)
        {
            return this.C1Json(CollectionViewHelper.Edit(requestData, item =>
            {
                var error = string.Empty;
                var success = true;
                try
                {
                    var index = sourceData.FindIndex(u => u.Id == item.Id);
                    sourceData.RemoveAt(index);
                }
                catch (Exception e)
                {
                    error = e.Message;
                    success = false;
                }
                return new CollectionViewItemResult<DatesData>
                {
                    Error = error,
                    Success = success,
                    Data = item
                };
            }, () => converter != null ? converter(sourceData) : sourceData));
        }
    }
}

Add View

In Code - Index.cshtml

DatesData.cs
Copy Code
@(Html.C1().FlexGrid()
  .Id("convertedGrid")
  .AllowAddNew(true)
  .AllowDelete(true)
  .AutoGenerateColumns(false)
  .Bind(cvb => cvb.Bind(Url.Action("Converted_ReadDatesData"))
                  .Create(Url.Action("Converted_CreateDatesData"))
                  .Update(Url.Action("Converted_UpdateDatesData"))
                  .Delete(Url.Action("Converted_DeleteDatesData")))
  .Columns(columns =>
  {
     columns.Add(column => column.Binding("Id").IsReadOnly(true).Visible(false));
     columns.Add(column => column.Binding("UtcDateTime").Format("dd/MM/yyyy HH:mm:ss").Width("*"));
     columns.Add(column => column.Binding("LocalDateTime").Format("dd/MM/yyyy HH:mm:ss").Width("*"));
     columns.Add(column => column.Binding("UnspecifiedDateTime").Format("dd/MM/yyyy HH:mm:ss").Width("*"));
  })
  .Filterable(f => f.DefaultFilterType(FilterType.Both)))