Saturday, August 27, 2016

Handling Sitecore DateTime Fields - Client and Server Side

I was in a tricky situation when I was working on one of my SPEAK page and I had certain date fields on the page. Adding to that complexity I wanted to allow user to be able to select time as well.

I decided to use SPEAK DatePicker and TimePicker (not documented by Sitecore) components. I had to use two different components as DatePicker allows you to only pick up date.

Note: Sitecore SPEAK TimePicker component will appear in the design layout -> Add Renderings option and you can find its JavaScript files at this location WebsiteRoot\sitecore\shell\client\Business Component Library\version 2\Layouts\Renderings\Common\TimePickers

One might ask why is it a challenge? Well, before I could pass my date field value to my entity service I have to manipulate the date as the inputs are coming from two different fields and it should be in a way that Sitecore understands it on the servers side.

So I had three  different formats to handle -

  1. Combining Date and Time picker format
  2. JavaScript native date format 
  3. Sitecore server side ISO date format

Handling it on client side (in JavaScript)

I created these functions to help me combine DatePicker and TimePicker values (in "Thhmmss" format) and return me one single date as shown below

        GetDateTime: function (date, strTime) { //date is from DatePicker.getDate() & strTime is TimePicker.get("time") function
            if (date != null) {
                var dtNewDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
                console.log("Date without time: " + dtNewDate);
                if ((typeof strTime != 'undefined') || (strTime != "")) {
                    strTime = strTime.substring(strTime.indexOf("T")+1, strTime.length);
                    console.log("Time Value: " + strTime);
                    var hours = Math.floor(strTime.substring(0, 2)); //To avoid NaN values (if parseInt was used)
                    var mins = Math.floor(strTime.substring(2, 4));
                    var secs = Math.floor(strTime.substring(4, 6));
                    console.log("Hours : Minutes : Seconds =>  " + hours + " : " + mins + " : " + secs);
                    dtNewDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), hours, mins, secs, 0);
                console.log("Date being returned : " + dtNewDate.toDateString());
                return dtNewDate;
                return null;

Also once I retrieve date from Sitecore and if they happen to be blank (or not set) I have to show that appropriately on DatePicker and TimePicker components. For that I created couple of other functions

        GetDateString: function(date)
            if (date.getFullYear() > 0) //Sitecore sets year as zero (if date is not set)
                return (date.getMonth() + 1) + "/" + date.getDate() + "/" + date.getFullYear(); //to show in mm/dd/yyyy format
                return "";

        GetTimeString: function (date) {
            if (date.getFullYear() > 0)
                return this.pad(date.getHours()) + ":" + this.pad(date.getMinutes());
                return "";

Handling it on ServerSide

Despite of date being sent appropriately to the entity service, when Sitecore was persisting the date it was setting the value as 1/1/0001. This was for a simple reason that you need to convert it into ISO date for Sitecore. I figured this out from this blog

So I had to do this:

StartTime = DateUtil.IsoDateToDateTime(entity.Fields["Start Time"].Value);

Few other important links from Sitecore documentation

Date / Time Types
Date / Time Best Practices
Date / Time Conversions

Hope this helps