getting number of working days between start date and end date

akhil_kusa
ServiceNow Employee
ServiceNow Employee

I'm new to learning ServiceNow, and I'm developing a mock PTO (Paid Time Off) application. I'm encountering difficulties in calculating the business days between two dates and checking for insufficient PTO balance. Below are my client script and script includes. Could you please review them and provide corrections?

ClientScript :

 

 

function onChange(control, oldValue, newValue, isLoading, isTemplate) {
    if (isLoading || newValue === '') {
        return;
    }

    var start = g_form.getValue('start_date');
    var balance = parseFloat(g_form.getValue('balance'));


    //Type appropriate comment here, and begin script below
    var ga = new GlideAjax('PTOAjax');
    ga.addParam('sysparm_name', 'getDatediff');
    ga.addParam('sysparm_start', start);
    ga.addParam('sysparm_end', newValue);

    ga.getXML(getDuration);


    function getDuration(response, balance) {
        var answer = response.responseXML.documentElement.getAttribute("answer");
        var days = (answer / (1000 * 60 * 60 * 24)) + 1;

        if (answer > balance) {
            g_form.addErrorMessage("Insufficient PTO");
            g_form.clearValue('duration');
            g_form.clearValue('end_date');

        } else {
            g_form.clearMessages();
            g_form.setValue('duration', days);
        }
    }

 

 

 

Script Include:

 

 

    getDatediff: function() {
        var startDate = new GlideDateTime();
        startDate.setDisplayValue(this.getParameter('sysparm_start'));
        var endDate = new GlideDateTime();
        endDate.setDisplayValue(this.getParameter('sysparm_end'));

        var schedule = new GlideSchedule('2d37aaa69781c2102z0036e71153afd9', gs.getProperty('glide.sys.default.tz'));

        var duration1 = schedule.duration(startDate, endDate);
        return duration1.getNumericValue();

    },

type: 'PTOAjax'

 

 

 

Appreciate your quick help!

 

@Ankur Bawiskar 

11 REPLIES 11

Harish KM
Kilo Patron
Kilo Patron

Hi @akhil_kusa can try the below? Not tested

getDatediff: funtion() {
var start = this.getParameter('sysparm_start');
var end =this.getParameter('sysparm_end');
var startDate = new GlideDateTime(start);

var endDate = new GlideDateTime(end);

// Create a GlideSchedule object with the appropriate timezone

var tz = gs.getProperty('glide.sys.default.tz').toString();
var schedule = new GlideSchedule('2d37aaa69781c2102z0036e71153afd9', tz);

// Calculate the duration between the start and end dates based on the schedule
var duration = schedule.duration(startDate, endDate);

// Return the numeric value of the duration
return duration.getNumericValue();
}

 

Client script

function onChange(control, oldValue, newValue, isLoading, isTemplate) {

    

    if (isLoading || newValue === '') {

        return;

    }

 

    

    var start = g_form.getValue('start_date');

    var balance = parseFloat(g_form.getValue('balance'));

 

    var ga = new GlideAjax('PTOAjax');

    ga.addParam('sysparm_name', 'getDatediff');

    ga.addParam('sysparm_start', start);

    ga.addParam('sysparm_end', newValue);

 

    

    ga.getXMLAnswer(getDuration);

 

    

    function getDuration(answer) {

       

        var result = answer;

        

        var days = (result / (1000 * 60 * 60 * 24)) + 1;

 

        

        if (result > balance) {

            // Display error message for insufficient PTO

            g_form.addErrorMessage("Insufficient PTO");

            // Clear values for duration and end date fields

            g_form.clearValue('duration');

            g_form.clearValue('end_date');

        } else {

            // Clear any existing error messages

            g_form.clearMessages();

            // Set the duration value in the form

            g_form.setValue('duration', days);

        }

    }

}

Regards
Harish

akhil_kusa
ServiceNow Employee
ServiceNow Employee

Thanks for the response @Harish KM . No, the output is same. I see 1 in duration which means (result / (1000 * 60 * 60 * 24)) has nothing. and my Field name for onChange is endDate.

M Ismail
Tera Guru

Hi @akhil_kusa,

Your implementation approach for calculating the difference between two dates in business days and checking for insufficient PTO balance using GlideAjax in ServiceNow is on the right track. However, there are a few adjustments and clarifications needed to ensure it functions correctly. Let's review and correct your code.

### Client Script

In your client script, the callback function `getDuration` does not correctly handle the balance check because the `balance` parameter is not being used or passed correctly. Let's adjust that part. Moreover, the calculation for days seems to assume that the `answer` is in milliseconds, which is not necessary since your script include will return the duration in seconds if using GlideDuration.

Here's the corrected version:


function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}

var start = g_form.getValue('start_date');
var balance = parseFloat(g_form.getValue('balance'));

// Initialize GlideAjax
var ga = new GlideAjax('PTOAjax');
ga.addParam('sysparm_name', 'getDatediff');
ga.addParam('sysparm_start', start);
ga.addParam('sysparm_end', newValue);
ga.getXMLAnswer(getDuration); // Use getXMLAnswer for simpler handling

function getDuration(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
var days = parseInt(answer); // Assuming answer is the duration in days

if (days > balance) {
g_form.addErrorMessage("Insufficient PTO Balance.");
g_form.clearValue('duration');
g_form.clearValue('end_date');
} else {
g_form.clearMessages();
g_form.setValue('duration', days.toString()); // Make sure to convert days back to string
}
}
}
```

### Script Include

Your Script Include looks mostly fine, but ensure it's set to `client-callable` so it can be accessed from client scripts. Also, the method `getDatediff` should correctly calculate business days between the start and end dates. Your current implementation seems correct, but ensure that the GlideSchedule sys_id and time zone property are correctly set for your instance.

Here's a slightly polished version to ensure clarity:


var PTOAjax = Class.create();
PTOAjax.prototype = {
initialize: function() {
},

getDatediff: function() {
var startDate = new GlideDateTime();
startDate.setDisplayValue(this.getParameter('sysparm_start'));
var endDate = new GlideDateTime();
endDate.setDisplayValue(this.getParameter('sysparm_end'));

var schedule = new GlideSchedule('2d37aaa69781c2102z0036e71153afd9', gs.getSession().getTimeZoneName());

var duration = schedule.duration(startDate, endDate); // This returns a GlideDuration object
return duration.getNumericValue(); // getNumericValue returns the duration in seconds
},

type: 'PTOAjax'
};
```


Please hit helpful and accept this as a solution if it solved your problem.
Thank you!

akhil_kusa
ServiceNow Employee
ServiceNow Employee

Thanks for the response @M Ismail.

 

I have tried the provided code. But nothing is being returned in the duration. I'm not sure what the issue is. 

For sys_id, Is it appropriate to obtain the it by opening the form, right-clicking, and copying it from there? If not, could you please provide the correct method? and for time zone i just using gs.getProperty('glide.sys.default.tz') or US/Pacific from dev ref doc