Friday, May 22, 2015

Get Sharepoint current datetime in javascript for Sharepoint Online

First of all let’s clarify what I mean by Sharepoint current datetime in the title. This is the datetime which you can see in Created column when create new item in the list or upload new document to the doclib. As you probably know internally Sharepoint stores all datetimes in content database in UTC format. In the Site settings > Regional settings it is possible to specify timezone for the current site. Depending on selected timezone Sharepoint will show datetimes to end users (if you will change timezone and update list view, values in Created and Modified fields will be changed). I.e. Sharepoint current datetime is not always the same as server date time which is set in OS.

On practice we often need to get Sharepoint current datetime and server datetime, e.g. when want to display news which are not older than N days. In order to do that we will get server current datetime and compare it with Created/Modified fields of the news. The question is how to get this datetime in the javascript? We are talking about javascript because this is the basic way currently to create custom components for Sharepoint Online.

One of the ways is to use _spPageContextInfo.clientServerTimeDelta variable which is defined like that:

   1: clientServerTimeDelta: new Date("2015-05-21T16:54:00.0000000Z") - new Date()

If you will check my other article How to get URL of current site collection and other server side properties on client site in Sharepoint, you will find that date defined in string in example above is current UTC date time:

   1: sb.Append("\", clientServerTimeDelta: new Date(\"");
   2: sb.Append(DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture));
   3: sb.Append("\") - new Date()");

In javascript “new Date()” will create datetime object created for the local client’s timezone. I.e. _spPageContextInfo.clientServerTimeDelta contains bias between client’s current datetime and server’s UTC current datetime. When we need server’s current UTC datetime for comparing it with Created/Modified date, we may do it like this:

   1: var d = new Date();
   2: var serverDateTimeNow = _spPageContextInfo.clientServerTimeDelta + d;

There will be difference with actual server time depending on how late above code will be executed, but not crucial. The problem is that _spPageContextInfo.clientServerTimeDelta may not be always available on your page, so let’s consider other approach as well.

Interesting solution was posted by colleague Vadim Gremyachev here: Get current server datetime through javascript REST. However you may face with cross domain request problem when will try to use this approach in Sharepoint app (apps have own sub domains). Also when offset is calcuated:

   1: var offset = data.d.Information.Bias / 60.0;

it doesn’t takes into consideration daylight bias. I.e. more correct approach is the following:

   1: var offset = (data.d.Information.Bias + data.d.Information.DaylightBias) / 60.0;

(there is also StandardBias property but it is set to 0 in examples I saw. For safety you may add it as well). In order to be able to use it in Sharepoint app javascript object model should be used:

   1: var context = new SP.ClientContext(appWebUrl);
   2: var factory = new SP.ProxyWebRequestExecutorFactory(appWebUrl);
   3: context.set_webRequestExecutorFactory(factory);
   4:  
   5: var hostContext = new SP.AppContextSite(context, postsArchiveURL);
   6: var web = hostContext.get_web();
   7: context.load(web);
   8:  
   9: context.executeQueryAsync(function () {
  10: create new document or item)
  11:     var regionalSettings = web.get_regionalSettings();
  12:     context.load(regionalSettings);
  13:     context.executeQueryAsync(
  14:         function () {
  15:             var timeZone = regionalSettings.get_timeZone();
  16:             context.load(timeZone);
  17:             context.executeQueryAsync(
  18:                 function () {
  19:                     var info = timeZone.get_information();
  20:                     var offset = (info.get_bias() + info.get_daylightBias()) / 60.0;
  21:                     var serverDateTimeNow =
  22: new Date(new Date().getTime() - offset * 3600 * 1000).toISOString();
  23:                     console.log("serverDateTimeNow: " + serverDateTimeNow);
  24:                 },
  25:                 function (sender, args) {
  26:                     console.log(args.get_message());
  27:                 }
  28:             );
  29:         },
  30:         function (sender, args) {
  31:             console.log(args.get_message());
  32:         }
  33:     );
  34: }, function(sender, err) {
  35:     console.log(err.get_message());
  36: });

I intentially converted serverDateTime variable to string using toISOString() function, because in this format it may be added to the CAML query for comparing with Created or Modified date.

In order to get Sharepoint current datetime we need to combine 2 approaches: to the server’s current UTC datetime

   1: var serverDateTimeNow = _spPageContextInfo.clientServerTimeDelta + d;

add offset like shown in example above. As result we will get time which is almost the same that is shown in Created/Modified fields. Hope that this information will help you in your work.

Update 2016-12-23. There is an issue with the shown approach of calculating serverDateTimeNow. See another post Get current server date time via javascript object model in Sharepoint which shows more correct way to calculate:

   1: var currentServerDateTime = new Date(new Date().getTime() + _spPageContextInfo.clientServerTimeDelta);

with last approach you will get correct datetime object in serverDateTimeNow variable.

2 comments:

  1. Hi,

    On the pages when I try to user _spPageContextInfo.clientServerTimeDelta + d; where d is new Date()as you mentioned I get a string. How do we usually add clientServerTimeDelta to get proper time?

    ReplyDelete
  2. Sharepointer,
    it looks like I posted pseudocode there, thank you for noticing it. Try this one:
    new Date(_spPageContextInfo.clientServerTimeDelta + d.getTime())

    ReplyDelete