Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Schedule end datetime is not correct

Brian Gil
Tera Expert

Hello Community,

 

I am trying to calculate an end date given a start date and a duration (1 second) using a schedule. I am using the "8-5 weekdays excluding holidays" schedule because I am really trying to calculate the nearest business day, which can include the current day.  

 

I tried techniques using both DurationCalculator and GlideSchedule APIs, but get unexpected results. Further, I am getting inconsistent results when comparing the two techniques.

 

I cannot explain this behavior and not sure if this issue is related to the schedule (our schedule was erroneously changed to 10am-7pm), a possible bug in the APIs, or my understanding of the APIs. 

 

Here is the code for method 1 (DurationCalculator with schedule sys_id removed):

 

var dates = [
                      '2023-11-10 00:00:00', //business day
                      '2023-11-11 00:00:00' //weekend
                    ];

gs.log("Method 1 (DurationCalculator)..");
for (var i in dates){
    gs.log(i + ".) startDate: " + dates[i]);
    var seconds = 1;
    var startDate = new GlideDateTime(dates[i]);	
    var dc = new DurationCalculator();	
    dc.setSchedule('<sys_id>', 'US/Eastern');
    dc.setStartDateTime(startDate);
    dc.calcDuration(seconds);
    gs.log(i + ".) startDate + 1sec: " + dc.getEndDateTime() + "\n");
}

 

 

Here is the code for method 2 (GlideSchedule with schedule sys_id removed):

 

var dates = [
                      '2023-11-10 00:00:00', //business day
                      '2023-11-11 00:00:00' //weekend
                    ];

gs.log("Method 2 (GlideSchedule)...");
for (var j in dates){
    gs.log(j + ".) startDate: " + dates[j]);
    var milliseconds = 1000;
    var startDate = new GlideDateTime(dates[j]);
    var dur = new GlideDuration(milliseconds);
    var sched = new GlideSchedule('<sys_id>', 'US/Eastern');
    var end = sched.add(startDate, dur);
    gs.log(j + ".) startDate + 1sec: " + end.getDisplayValue() + "\n");
}

 

 

Here is a screenshot of the script output:

time is all zeros.png

Method 2 output makes sense since our schedule starts at 10AM.  Where does method 1's 15:00:01 (3PM) come from?  Why does not method 1 and 2 output match?

 

Here is an additional screenshot where the start-date time was changed to after the 10AM-7PM schedule, namely 20:00:00 (8PM).  Again, these results do not make sense because I would think that after the business day, the result should be the next business day.

after business hours.png

 

To muddy the waters further, when I run gs.calcDateDiff(<date 1>, <date 2>, bool), I also get unexpected results:

 

gs.log(gs.calDateDiff('2023-11-13 10:00:00', '2023-11-13 15:00:05', false));

 

Output:

BrianGil_0-1698874392238.png

I would expect 5 hours, but the result is 3 hours. Can anyone help explain these anomalies? Thanks in advance.

 

1 ACCEPTED SOLUTION

Thanks a bunch Tai Vu. I was able to apply your UTC conversion knowledge to my DurationCalculator problem. 

 

Essentially, I appended ' 15:00:01' (end of day) to my startDate string, and now the schedule works as expected.  Here is the working example code:

 

/**
 * Compare a selected date to a start date plus X business days
 * 
 * notes:
 * schedule uses 10-7 schedule and time is converted to UTC 
 * if startDate is Sat/Sun, acts like it is Mon, which works for my use case
 */

var startDate = '2023-11-02 15:00:01';  //use time after end of current day to exclude day
var days = 7;  //business days to add to start date
var selectedDate = '2023-11-13';  //compare this date to startDate + days
var startPlusXDays;

var startGDT = new GlideDateTime(startDate);
var selectedGDT = new GlideDateTime(selectedDate);
selectedGDT = selectedGDT.getDate();  //truncate time for to compare date

var dc = new DurationCalculator();
dc.setSchedule('<schedule_sys_id>', 'US/Eastern');  //schedule excludes weekends and holidays
dc.setStartDateTime(startGDT);
dc.calcDuration(days * 9 * 3600);  //calculate duration in seconds; seconds must be > 0
startPlusXDays = dc.getEndDateTime().getDate();  //truncate time to compare date

gs.info("start date=    " + startDate);
gs.info("+business days=" + days);
gs.info("end date=      " + startPlusXDays.toString());
gs.info("selected date= " + selectedGDT.toString());
gs.info("compare=       " + selectedGDT.compareTo(startPlusXDays));  //returns -1/0/1

 

View solution in original post

2 REPLIES 2

Tai Vu
Kilo Patron
Kilo Patron

Hi @Brian Gil 

gs.log(gs.calDateDiff('2023-11-13 10:00:00', '2023-11-13 15:00:05', false));

"I would expect 5 hours, but the result is 3 hours. Can anyone help explain these anomalies?"

 

It's using the default calendar. You can find on below.

Name: Monday thru Friday (9 - 5)

URL: https://<instance_name>/sys_calendar_list.do)

 

So it will only calculate the duration inside the defined hours. 

If you're in US Eastern Time Zone => Convert all to UTC, it will be:

2023-11-13 10:00:00 (US/Eastern) => 2023-11-13 14:00:00 (UTC)

2023-11-13 15:00:00 (US/Eastern) => 2023-11-13 19:00:00 (UTC)

Default Calendar (UTC: 09:00 - 17:00) => 17:00:00 - 14:00:00 => 03:00:00

 

Let's have a look in the API definition. There's couple of points we need to notice.

 

TaiVu_1-1698909991503.png

 

 

Cheers,

Tai Vu

 

 

Thanks a bunch Tai Vu. I was able to apply your UTC conversion knowledge to my DurationCalculator problem. 

 

Essentially, I appended ' 15:00:01' (end of day) to my startDate string, and now the schedule works as expected.  Here is the working example code:

 

/**
 * Compare a selected date to a start date plus X business days
 * 
 * notes:
 * schedule uses 10-7 schedule and time is converted to UTC 
 * if startDate is Sat/Sun, acts like it is Mon, which works for my use case
 */

var startDate = '2023-11-02 15:00:01';  //use time after end of current day to exclude day
var days = 7;  //business days to add to start date
var selectedDate = '2023-11-13';  //compare this date to startDate + days
var startPlusXDays;

var startGDT = new GlideDateTime(startDate);
var selectedGDT = new GlideDateTime(selectedDate);
selectedGDT = selectedGDT.getDate();  //truncate time for to compare date

var dc = new DurationCalculator();
dc.setSchedule('<schedule_sys_id>', 'US/Eastern');  //schedule excludes weekends and holidays
dc.setStartDateTime(startGDT);
dc.calcDuration(days * 9 * 3600);  //calculate duration in seconds; seconds must be > 0
startPlusXDays = dc.getEndDateTime().getDate();  //truncate time to compare date

gs.info("start date=    " + startDate);
gs.info("+business days=" + days);
gs.info("end date=      " + startPlusXDays.toString());
gs.info("selected date= " + selectedGDT.toString());
gs.info("compare=       " + selectedGDT.compareTo(startPlusXDays));  //returns -1/0/1