Create a Catalog Client Script to Ensure Entered Date is Not Before Next Business Date

jmiskey
Kilo Sage

I have a Catalog Item where I am trying to create an onChange Catalog Client Script that ensures that the selected date is NOT before the next Business Date.  So, if they enter a date today, it cannot be before tomorrow's date (since tomorrow is not a weekend).

 

I had never used CoPilot before, and thought I would give it a shot to see if it could write the script for me.  Much to my surprise, it came up with code that works MOST of the time.  It just doesn't work if they choose tomorrow's date.  I added an alert to my code, and I think I see the issue.  I think it might be due to the GMT offset of 4 hours for our system.

 

Here is the code that it came up with (after I amended it to reflect my field name and added my alert):

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

  // Parse the entered date
  var enteredDate = new Date(newValue);
  enteredDate.setHours(0, 0, 0, 0); // Normalize time
  // Get today's date
  var today = new Date();
  today.setHours(0, 0, 0, 0);
  // Calculate the next business day
  var nextBusinessDay = new Date(today);
  nextBusinessDay.setDate(today.getDate() + 1);
  // Skip weekends
  while (nextBusinessDay.getDay() === 0 || nextBusinessDay.getDay() === 6) {
    nextBusinessDay.setDate(nextBusinessDay.getDate() + 1);
  }

  // Compare entered date with next business day
  alert('Entered Date: ' + enteredDate + '\n' + 'Next Business Day: ' + nextBusinessDay);
  if (enteredDate < nextBusinessDay) {
	alert('Date must be on or after the next business day!');
    g_form.setValue('u_check_due_date', '');
  }
   
}

and here is the alert I get when I choose tomorrow's date (2025-07-24) in my "u_check_due_date" field:

jmiskey_0-1753302907223.png

 

As you can see, if erroneously is changing my entered date to 2025-07-23, presumably when it is trying to remove the time component. 

 

Can anyone fix the code so that it does not do that, and functions properly?

 

Thanks

 

1 ACCEPTED SOLUTION

Ankur, I did some deep digging yesterday after I posted this, and found that we had done this once a long time ago, using a GlideAjax call very similar to your post.

 

Here is out Catalog Client Script:

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

	//Ensure Check Due Date is not any sooner than next Business Day
	var cdate = g_form.getValue('u_check_due_date');  //get entered Check Due Date
	var sdate = new Date();  //start date is current date/time  
	var ndays = 1;  //next business day

	var ajax = new GlideAjax('global.BusinessDateUtils');  
	ajax.addParam('sysparm_name','getBusinessDate');  
	ajax.addParam('sysparm_startdate', sdate);  
	ajax.addParam('sysparm_numdays', ndays); 
	ajax.getXML(doSomething);  

	function doSomething(response){  
		var answer = response.responseXML.documentElement.getAttribute("answer");  
		//Make sure Check Due Date is on or after next Business Date
		if (answer > cdate) {
			alert("You must select a date on or after next Business Day");
			g_form.setValue('u_check_due_date','');
		}
	}

}

and here is the Script Include we created for it year ago.  One nice feature is that you feed in the number of business days you want as a parameter (so it is not hard-coded in the function).  So it is dynamic and can be used for any number of business days:

var BusinessDateUtils = Class.create();
BusinessDateUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

	//Calculate business date from starting date and number of days (uses Weekdays plus Holidays calendar)
	getBusinessDate: function(){
		var startDate = this.getParameter('sysparm_startdate');
		var numDays = this.getParameter('sysparm_numdays');

		//var gdt = new GlideDateTime();
		var gdt = startDate;
		var dc = new DurationCalculator();
		dc.setSchedule('8746beb20ffb9a00e3b522d8b1050ebf'); //Weekdays excluding holidays schedule
		dc.setStartDateTime(gdt);
		dc.calcDuration(24*3600*numDays); //1 business day = 24 hours

		var edt= new GlideDateTime(dc.getEndDateTime());
		edt = edt.toString().split(' ');
		var dt = edt[0];
		
		return dt;
	},	

	type: 'BusinessDateUtils'
});

View solution in original post

8 REPLIES 8

Swapna Abburi
Mega Sage
Mega Sage

Hi @jmiskey 

Did you try by removing below two lines:

enteredDate.setHours(0, 0, 0, 0);
  today.setHours(0, 0, 0, 0);

Bhimashankar H
Mega Sage

Hi @jmiskey ,

 

Could you please elaborate a little bit more, about the date selection criteria ?

Is it ?

1.  Selected date should be after next business day only(After whole 24 hours of next business day)? OR

2. Selected date can be next business day, mean it will not be today's date OR

3. Selected date should be after 24 hours of today's date but not the before, next business day.

OR

simple explain in terms of hours .

 

It will remove the time because you added to remove the time.

enteredDate.setHours(0, 0, 0, 0); // Normalize time

today.setHours(0, 0, 0, 0);

These above 2 lines are setting the time component to 00:00:00



Thanks,
Bhimashankar H

 

-------------------------------------------------------------------------------------------------
If my response points you in the right directions, please consider marking it as 'Helpful'. Thanks!

Option 2.  Time is of no meaning.  They just cannot choose today.  And if "today" happens to be a Friday, they cannot choose the following Saturday or Sunday (cannot choose a date any earlier than the following Monday).

 

Ankur Bawiskar
Tera Patron
Tera Patron

@jmiskey 

check this and enhance it as per your requirement, better to use your existing schedule and check if that date selected falls in that schedule

Variable Date no less than 5 business days 

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader