1

I am storing a datetime value in a cookie using ASP.Net server-side C# code. On client-side, I am reading the date and converting it to UTC using JavaScript. The code for this is as given below.

Storing date time in ASP.Net

//DateTime.Now depends on location of web server
HttpCookie cookie = new HttpCookie("xyz", DateTime.Now.ToUniversalTime().ToString());
Response.Cookies.Add(cookie);

JavaScript code to read date time sent by ASP.Net

//cDate depends on user's location
//c is value read from cookie named 'xyz'
var cDate = new Date(c);
var cDate_utc = new Date(cDate.getUTCFullYear(), cDate.getUTCMonth(), cDate.getUTCDate(), cDate.getUTCHours(), cDate.getUTCMinutes(), cDate.getUTCSeconds());

When the end user's location is different from ASP.Net web server's location, then the datetime value in the cookie will be incorrectly interpreted by JavaScript. For example, in one case the value stored in cookie was 10/31/2015 7:29:54 PM and there is no way for JavaScript to know that this is UTC which means it would be incorrectly parsed on client-side.

Question: How can I pass DateTime value from ASP.Net to JavaScript in above scenario so it interprets correctly in JavaScript no matter what the geographical locations of end user's browser and ASP.Net web server are?

UPDATE with a solution that worked

After a lot of research, I came up with the following. The bottom line is to always work in UTC so day light savings does not cause problems with the programming logic.

  • Pass UTC and not local date time from ASP.Net server-side to client-side via a cookie using individual components of date time. Do not pass a date time string but individual components of date time as a comma-delimited list in following format: year,month, day, hours, min, sec, milliseconds. Passing individual components rather than a date time string from ASP.Net is better since JavaScript Date constructor can behave in an erratic manner when parsing a string especially if the format of string passed is not what the constructor likes. Passing individual components also helps in cross-browser consistent behavior since the Date constructor with individual components works well across all major browsers.
  • On client-side, read the cookie value and instantiate a Date object that will be the local time on browser side corresponding to server-side UTC time
  • Now you have the server-side ASP.Net passed date time in local date time on client-side. This might work for some cases, but can cause sudden surprises on client-side when daylight savings happens, so it's best to convert this client-side date to UTC.

Pass date time in UTC to client-side from ASP.Net

 DateTime utcDateTime = DateTime.Noe.ToUniversalTime();
 System.Text.StringBuilder sb = new System.Text.StringBuilder();
 sb.Append(utcDateTime.Year);
 sb.Append(",");
 sb.Append(utcDateTime.Month - 1); //since JavaScript uses a 0 based index for month
 sb.Append(",");
 sb.Append(utcDateTime.Day);
 sb.Append(",");
 sb.Append(utcDateTime.Hour);
 sb.Append(",");
 sb.Append(utcDateTime.Minute);
 sb.Append(",");
 sb.Append(utcDateTime.Second);
 sb.Append(",");
 sb.Append(utcDateTime.Millisecond);
 HttpCookie cookie = new HttpCookie("xyz", sb.ToString());
 Response.Cookies.Add(cookie); 

Get UTC date time in JavaScript for passed ASP.Net date time

   var c = getCookie("xyz");//getCookie is a custom JavaScript function to read cookie value
    if (c) {

        var dateArray = c.split(",");
        //get local date time corresponding to ASP.Net passed UTC date time
        var cDate = new Date( Date.UTC(dateArray[0], dateArray[1],dateArray[2], dateArray[3], dateArray[4], dateArray[5], dateArray[6])) ;
        //get UTC date time so day light savings does not cause issues in logic on client-side
        cDate_utc = new Date(cDate.getUTCFullYear(), cDate.getUTCMonth(), cDate.getUTCDate(), cDate.getUTCHours(), cDate.getUTCMinutes(), cDate.getUTCSeconds());
        logInfo("date from cookie in utc is " + cDate_utc);
    }
Sunil
  • 20,653
  • 28
  • 112
  • 197
  • 1
    Take a look at moment.js. http://momentjs.com/docs/ – dbugger Nov 01 '15 at 18:37
  • @dbugger, How would the library know that `10/31/2015 7:29:54 PM` was in UTC? In my scenario a UTC value like `10/31/2015 7:29:54 PM` is being stored in the cookie. – Sunil Nov 01 '15 at 18:45
  • 1
    This post might help: http://stackoverflow.com/questions/2532729/daylight-saving-time-and-time-zone-best-practices – Asons Nov 01 '15 at 18:49

2 Answers2

2

Although the comments already point you in the right direction:

If you use moment.js it will by default use UTC format and even if it wasn't (for completeness sake) you can use this format to specify an offset: 2013-02-08 09:30:26.123+07:00

You call the code like this: moment(cDate, $format);

online Thomas
  • 8,864
  • 6
  • 44
  • 85
1

If I understand your question correctly, you want to convert the date passed in the cookie from UTC to local time.

You can use Date.prototype.getTimezoneOffset()

getTimezoneOffset returns the offset from UTC to local time in minutes.

Adjust locally by subtracting the offset minutes...

new Date(dateServer.getTime() - ((60 * 1000) * dateServer.getTimezoneOffset()))

Here's an example...

    var dateJan;
    var dateJul;
    var dateValue;

    var divLocal;
    var divServer;

    var timezoneOffset;

    dateValue = new Date('10/31/2015 7:29:54 PM')

    divServer = document.getElementById('serverUTCTime');
    divLocal = document.getElementById('localTime')

    divServer.innerHTML = 'from server = ' + dateValue.toString();

    // Get dates for Jan & Jul
    dateJan = new Date(dateValue.getFullYear(), 0, 1);
    dateJul = new Date(dateValue.getFullYear(), 6, 1);

    // Get timezone offset
    timezoneOffset = Math.max(dateJan.getTimezoneOffset(), dateJul.getTimezoneOffset());

    // Check if daylight savings
    if (dateValue.getTimezoneOffset() < timezoneOffset) {
      // Adjust date by Jan offset
      dateValue = new Date(dateValue.getTime() - ((60 * 1000) * dateJan.getTimezoneOffset()));
    } else {
      // Adjust date by Jul offset
      dateValue = new Date(dateValue.getTime() - ((60 * 1000) * dateJul.getTimezoneOffset()));
    }

    divLocal.innerHTML = 'to local = ' + dateValue.toString();
<div id="serverUTCTime"></div>
<br/>
<div id="localTime"></div>
WhiteHat
  • 59,912
  • 7
  • 51
  • 133
  • How would the client-side know that the date format received from ASP.Net is in mm/dd/yyyy format. It could also have been in dd/mm/yyyy format. For example, if ASP.Net sent `10/11/2015 7:29:54 PM` how would JavaScript know whether the first part is month or day. I think that is a problem with passing the date string to Date object `new Date ('10/31/2015 7:29:54 PM')`. I think it would have been better if individual components were passed to the JavaScript Date object rather that the date time value received from ASP.Net. – Sunil Nov 01 '15 at 20:28
  • Also, not sure if day savings time would be accounted for by using this approach. I came across this in another stackoverflow post: " `getTimezoneOffset` returns the offset for the date and time you call it on. That offset can change when a time zone transitions in or out of daylight saving time. " – Sunil Nov 01 '15 at 20:42
  • 1
    see edit for daylight savings adjustment, as for format, force the same on both sides... – WhiteHat Nov 01 '15 at 22:08