Schedule-based Date/Time Addition

///Schedule-based Date/Time Addition

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;
By | 2018-07-09T14:59:56-06:00 October 26th, 2011|Categories: Business rules|Tags: , , |25 Comments

About the Author:

25 Comments

  1. Alan Sharp-Paul October 30, 2011 at 5:54 am - Reply

    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.

    • Mark Stanger October 31, 2011 at 6:35 am - Reply

      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

      • Alan Sharp-Paul November 4, 2011 at 3:13 pm - Reply

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

        • Mark Stanger February 14, 2013 at 2:26 pm - Reply

          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.

  2. Ruchi November 4, 2011 at 9:26 am - Reply

    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.

  3. James R Grinter November 8, 2011 at 5:03 pm - Reply

    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.)

    • Mark Stanger November 8, 2011 at 8:00 pm - Reply

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

  4. Catherine November 17, 2011 at 8:34 am - Reply

    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

    • Mark Stanger November 17, 2011 at 9:58 am - Reply

      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

  5. Ryan October 16, 2012 at 12:04 pm - Reply

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

    • Mark Stanger October 17, 2012 at 11:16 am - Reply

      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.

    • Daryll May 8, 2014 at 10:29 am - Reply

      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.

  6. Hiranmayee January 9, 2014 at 7:26 am - Reply

    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.

    • Mark Stanger January 9, 2014 at 7:39 am - Reply

      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);

  7. Hiranmayee January 9, 2014 at 11:21 pm - Reply

    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);
    }
    });

    • Mark Stanger January 10, 2014 at 7:50 am - Reply

      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’));
  8. Hiranmayee January 13, 2014 at 4:08 am - Reply

    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.

    • Mark Stanger January 13, 2014 at 5:14 am - Reply

      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.

  9. Hiranmayee January 13, 2014 at 5:39 am - Reply

    Thanks for all your help Mark

  10. David Martin Clavo February 18, 2014 at 9:22 am - Reply

    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

    • Mark Stanger February 18, 2014 at 9:31 am - Reply

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

      • MG October 8, 2015 at 8:59 am - Reply

        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).

  11. Amisha Parekh February 27, 2015 at 8:48 am - Reply

    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

  12. Sourabh Dhaygude July 28, 2017 at 9:10 am - Reply

    I always struggle with date time calculations and Mark is the guy who always helps me. Thanks Mark for all these posts!

    Kind regards,
    Sourabh

Leave A Comment