THURSDAY, JANUARY 19, 2017

Schedule-based Date/Time Addition

I

was recently asked to help a colleague figure out some date calculations based on a schedule. The requirement was to calculate a future date based on the existing value of a date/time field. I decided to document this solution (and come up with a solution for a similar problem…date addition from the current date/time based on a schedule). Working with dates and schedules can really be a pain if you don’t have good examples to work from so hopefully these help somebody at some point. Read on for the full scripts.

These scripts are designed to work in a ‘before’ business rule. To get them to work in a UI action you need to include ‘current.update();’ as the last line.

Add time based on schedule to current time

//Get a schedule by name to calculate duration
var schedRec = new GlideRecord('cmn_schedule');
schedRec.get('name', '8-5 weekdays');
if (typeof GlideSchedule != 'undefined')
   var sched = new GlideSchedule(schedRec.sys_id);
else
   var sched = new Packages.com.glide.schedules.Schedule(schedRec.sys_id);

//Get the current date/time in correct format for duration calculation
var currentDateTime = new GlideDateTime();
currentDateTime.setDisplayValue(gs.nowDateTime());

//Set the amount of time to add (in seconds)
var timeToAdd = 86400;
durToAdd = new GlideDuration(timeToAdd*1000);
var newDateTime = sched.add(currentDateTime, durToAdd, '');

//Set the 'requested_by_date' field to the new date/time
current.requested_by_date = newDateTime;

Add time based on schedule to current field value

//Get a schedule by name to calculate duration
var schedRec = new GlideRecord('cmn_schedule');
schedRec.get('name', '8-5 weekdays');
if (typeof GlideSchedule != 'undefined')
   var sched = new GlideSchedule(schedRec.sys_id);
else
   var sched = new Packages.com.glide.schedules.Schedule(schedRec.sys_id);

//Get the current date/time in correct format for duration calculation
var currentDateTime = current.requested_by_date.getGlideObject();

//Set the amount of time to add (in seconds)
var timeToAdd = 86400;
durToAdd = new GlideDuration(timeToAdd*1000);
var newDateTime = sched.add(currentDateTime, durToAdd, '');

//Set the 'requested_by_date' field to the new date/time
current.requested_by_date = newDateTime;

24 Comments

Alan Sharp-Paul 30-10-2011, 05:54

Thanks for the post. I’ve always used Packages.com.glide… for schedules scripting, I was just wondering what we’re supposed to do considering the fact that this post claims that our ability to use it will be phased out?

http://community.service-now.com/blog/slightlyloony/classes-and-more-classes-oh-my

Cheers,

Alan.

Reply
Mark Stanger 31-10-2011, 06:35

Hey Alan,

I think that will happen eventually, but they’ve been saying that for over a year now. My advice is to continue using whatever you need to get the job done. Avoid ‘Packages’ calls wherever you can, but in this case they are completely necessary. As you do that, it’s probably a good idea to make a note of which calls you’ve used (and where you’ve used them) just in case you have to go back and change the code later. My guess is that dev will probably have to provide some automated way of switching to the non-packages calls in the future because EVERYONE uses these in one place or another.

Mark

Reply
Alan Sharp-Paul 04-11-2011, 15:13

Very true. I was hoping that there was another way just in case. Thanks for the reply.

Reply
Mark Stanger 14-02-2013, 14:26

FYI, ‘Packages’ calls will start to be phased out in the upcoming ‘Calgary’ release. I’ve updated the scripts above to be compatible no matter which version you’re on. ServiceNow will also be providing a migration utility.

Reply
Ruchi 04-11-2011, 09:26

I want to check if the difference between the effective date and today’s date is 1 day / 9 business hours. I am trying to use this as an example but not sure how to check date difference based on schedule? is sched.sub /subtract method is available to calculate the difference? Thanks.

Reply
Mark Stanger 04-11-2011, 10:31

For calculating the difference between dates using a schedule I think this post has a better example.
http://www.servicenowguru.com/scripting/business-rules-scripting/calendar-based-incident-autoclose/

Reply
James R Grinter 08-11-2011, 17:03

Note that you can (and should) just use

new GlideDateTime();

these days. For Schedule, we’ll make the appropriate parts of that API accessible, and documented, without needing Packages calls before we phase them out (see CapaJC’s note on the SlightlyLoony blog post.)

Reply
Mark Stanger 08-11-2011, 20:00

Thanks for the tip! I’ve replaced the ‘GlideDateTime’ packages call above with the new code.

Reply
Catherine 17-11-2011, 08:34

Hi Mark,

In the Change Request App, do you know why the system would allow you to select a historical date(past date) in the End Date field when planning?

Example: Start Date is “today” Nov 17th 2011 and End Date is Nov 1st 2011.

How can I set the system to validate dates and not allow this to happen. Any ideas?

Thanks
Catherine

Reply
Mark Stanger 17-11-2011, 09:58

There’s no reason why it should other than the validation hasn’t been put in place. I’ve raised this issue to ServiceNow development but I don’t have a timeline for its addition to the product. It’s pretty easy to validate these types of things though. Here’s a link to some examples on the wiki.
http://wiki.service-now.com/index.php?title=Compare_Two_Date_Fields

Reply
Ryan 16-10-2012, 12:04

Is there a way to subtract a day from a schedule? When i introduce a netgative number the script no longer works.

Reply
Mark Stanger 17-10-2012, 11:16

Hey Ryan,
I’m pretty sure there is, but I don’t know what it is off the top of my head. You might need to ask this one on the forums. If you find anything out, let me know and I’ll be sure to update this article.

Thanks.

Reply
Daryll 08-05-2014, 10:29

I had this issue, this is what I can up with…

// Date Time variable taken from my form
var dateTime = g_form.getValue(‘u_date_and_time’);
// a duration number (minutes in this case)
var duration = g_form.getIntValue(‘u_duration’);

// Split up the Date and Time for manipulation and reordering
var dateSplit = dateTime.split(” “)[0];
var timeSplit = dateTime.split(” “)[1];

var date = dateSplit.split(“-“)[0];
var month = dateSplit.split(“-“)[1];
var year = dateSplit.split(“-“)[2];

var hours = parseInt(timeSplit.split(“:”)[0]);
var minutes = timeSplit.split(“:”)[1];
var seconds = timeSplit.split(“:”)[2];

// Reorder & combine dateTime and create the endDateTime
dateTime = (year + “-” + month + “-” + date + ” ” + hours + “:” + minutes + “:” + seconds);
// Where I added minutes on…
endDateTime = (year + “-” + month + “-” + date + ” ” + hours + “:” + minutes + duration + “:” + seconds);

// This allows you full flexibility with regards to changing any parts of the time or date and changing the order

In your case you could just do…

date = date – 1;

You may want to check that date isn’t 1 and if it is reduce the month by 1 and work out which month it is for the days then set the date to the last day of the previous month.
Not an ideal solution but it should help.

Reply
Hiranmayee 09-01-2014, 07:26

I found the error “Javascript compiler exception: Can’t find method com.glide.schedules.Schedule.add(string,string,string). ”

Error in line
var newDateTime = sched.add(currentDateTime, durToAdd, ”);

add() method can’t able to find in calgary release.

Reply
Mark Stanger 09-01-2014, 07:39

That’s probably because you’re instantiating ‘sched’ with a packages call…which no longer work in new Calgary instances. You’ll notice my code above works with both packages calls and the new code. Try replacing the ‘Packages’ line in your code with this.

var sched = new GlideSchedule(schedRec.sys_id);

Reply
Hiranmayee 09-01-2014, 23:21

I have already replaced my code with that still no output.
Here is my script –

Script include-
var AjaxHelperFunctions = Class.create();
AjaxHelperFunctions.prototype = Object.extendsObject(AbstractAjaxProcessor, {
datePastSLA: function() {
var firstDT = this.getParameter(‘sysparm_fdt’); //First Date-Time Field
var slaDays = this.getParameter(‘sysparm_sla_dt’);

var schedRec = new GlideRecord(‘cmn_schedule’);
schedRec.get(‘sys_id’, ‘090eecae0a0a0b260077e1dfa71da828’);
var sched = new GlideSchedule(schedRec.sys_id);
var timeToAdd = slaDays * 32400;
var durToAdd = new GlideDuration(timeToAdd*1000);
var newDateTime = sched.add(firstDT, durToAdd, ”);

var answer = ”;
answer = newDateTime;
return answer;
}

Client script

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
var stDt = g_form.getValue(‘u_start_date’);
var ajax = new GlideAjax(‘AjaxHelperFunctions’);
ajax.addParam(‘sysparm_name’, ‘datePastSLA’);
ajax.addParam(‘sysparm_fdt’, stDt);
ajax.addParam(‘sysparm_sla_dt’,’10’);
ajax.getXMLWait();
var answer = ajax.getAnswer();
g_form.setValue(‘u_end_date’,answer);
}
});

Reply
Mark Stanger 10-01-2014, 07:50

I’d be surprised if this worked in any release, let alone Calgary. The problem isn’t with the code I’ve supplied above, but you do have an issue with the date your passing from the client. The date is being passed as a string to your back-end function because that’s how the date values are formatted client-side. The ‘add’ method requires a ‘glideDateTime’ object, not a string. You’ll have to convert the string being passed into your function before using ‘sched.add’. Something like this should work better to replace the ‘var firstDT = this.getParameter(‘sysparm_fdt’); //First Date-Time Field’ line in your script above.

var firstDT = new GlideDateTime();
firstDT.setDisplayValue(this.getParameter(‘sysparm_fdt’));
Reply
Hiranmayee 13-01-2014, 04:08

Thanks Mark for your information.

It worked.

One question: Is there any way to check the method in a package because we faced issue because we didnt know what was the input parameter data type as well as output parameter.

Thanks in advance.

Reply
Mark Stanger 13-01-2014, 05:14

Unless ServiceNow has it documented somewhere (and I don’t think they do in this case) I don’t know how you would know unless you had used it before. A close examination of my code above would have told you the data type of the information being passed in but I can see how that might be overlooked. At least now you’ll know for next time. I would contact ServiceNow and request that they document GlideSchedule so it’s available in the future.

Reply
Hiranmayee 13-01-2014, 05:39

Thanks for all your help Mark

Reply
David Martin Clavo 18-02-2014, 09:22

Dear Mark,

Thanks for this article which has already helped me on several occasions.

Do you know of any way to perform a substract instead of an add?

I tried with:

var timeToAdd = -86400; // negative time
durToAdd = new GlideDuration(timeToAdd*1000);
var newDateTime = sched.add(currentDateTime, durToAdd, ”);

But sched.add just returns the same value as currentDateTime.

Use case: I have a task where I know the due date, its duration, and a schedule, and would like to calculate the start date accordingly.

Thanks in advance for your reply,
David

Reply
Mark Stanger 18-02-2014, 09:31

I haven’t tried this specifically, but you might try ‘sched.subtract’ instead.

Reply
MG 08-10-2015, 08:59

This unfortunately isn’t working – I have the same need as well. Not sure how to put in a negative duration (if that is even possible).

Reply
Amisha Parekh 27-02-2015, 08:48

Hi Mark,

I tried following code in background script.

var todaysDate = new GlideDateTime();
todaysDate.setDisplayValue(gs.nowDateTime());

gs.print(“todaysDate display value : ” + todaysDate);

My Timezone is US/Eastern but, this is still returning output in GMT format asour instance is in GMT format.

Could you please let me know if i am missing anything?

Thanks & Regards,
Amisha Parekh

Reply

Leave a Reply


Latest Comments

  • David: It appears that I can hit sys_properties table with REST. This works, but I haven’t yet discovered the...
  • Mark Stanger: Hey David, It doesn’t surprise me that scoped apps have made this more difficult. I’m not...
  • David: Mark, do you have an example of how to do this in a scoped app? It seems there are many hoops to jump through...
  • Mark Stanger: The only possibility is to create a system property to override this in your application. Check out the...