- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi Community,
I’m working on a Service Catalog Date/Time variable validation and would like confirmation or suggestions for improvement.
Variable Details
- Variable name: time_to_send_out_comms
- Variable type: Date/Time
- Used on: Service Request (SR)
Business Requirement1. Past Date/Time Validation
- The selected date/time must not be in the past
✅ If user selects a past date/time, show the error message:
“The time chosen to send out the communication occurs in the past, kindly select a future date/time to proceed.”
2. Minimum Lead Time – 2 Working Days (Hour‑Based)
- The selected date/time must be at least 2 working days after the current date/time
- Working days: Sunday to Thursday
(Friday and Saturday are non‑working days) - Lead time must be hour‑based, not just date‑based
Example
Current date/time:
13/May/2026 13:05:00 (Wednesday)Thank you✅ Valid selections
- 17/May/2026 13:06:00
- 17/May/2026 15:00:00
- Any date/time after the same HH:mm:ss on the 2nd working day
❌ Invalid selections
- 17/May/2026 13:04:00
- Any date/time before 17/May/2026 13:05:00
✅ If user does not allow 2 working days lead time, show the error message:
“Please allow two working days lead time for approvals and content review.”
Please provide with exact code so it will helpful to me.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hello @Sirri
Here is the updated onChange Client script:
function onChange(control, oldValue, newValue, isLoading) {
//Stop processing further code from running when the form initially loads with pre-existing values
if (isLoading) {
return;
}
// Stop processing further code from running when user clears the field, as there is nothing to validate
if (!newValue || newValue == '') {
return;
}
var pastMsg = "The time chosen to send out the communication occurs in the past, kindly select a future date/time to proceed.";
var leadMsg = "Please allow two working days lead time for approvals and content review.";
var weekendMsg = "Communications cannot be scheduled on a Friday or Saturday as these are non-working days. Please select a working day (Sunday–Thursday).";
// Month abbreviation to 0-indexed number mapping for display-style format (e.g., "11/May/2026 10:41:26")
var monthMap = {
'Jan': 0, 'Feb': 1, 'Mar': 2, 'Apr': 3,
'May': 4, 'Jun': 5, 'Jul': 6, 'Aug': 7,
'Sep': 8, 'Oct': 9, 'Nov': 10, 'Dec': 11
};
// Required to separate the date component from the time component for independent parsing
var dateParts = newValue.split(' ');
// Required to extract hour, minute, and second as separate values from the time string like "12:48:24"
var timeParts = dateParts[1].split(':');
var year, month, day;
//Please go through below links to understand below code:
/*
indexOf(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
split(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
parseInt(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
Date(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
*/
// For Date Time format: "11/May/2026 10:41:26"
if (dateParts[0].indexOf('/') !== -1) { // check whether date contain a forward slash
// Display-style format: "11/May/2026"
var dateComponents = dateParts[0].split('/'); // Splits "11/May/2026" into pieces: ["11", "May", "2026"]
day = parseInt(dateComponents[0], 10); // First piece "11" which is day = 11
month = monthMap[dateComponents[1]]; // Second piece "May" → look up in monthMap → month = 4 (0-indexed)
year = parseInt(dateComponents[2], 10); // Third piece "2026" → year = 2026
} else {
//For Date Time format: "2026-05-20" -- You can comment this if you don't need it.
var dateComponents = dateParts[0].split('-');
year = parseInt(dateComponents[0], 10);
month = parseInt(dateComponents[1], 10) - 1;
day = parseInt(dateComponents[2], 10);
}
// Required to construct a valid JavaScript Date; month is 0-indexed (0=Jan, 11=Dec)
var selectedDate = new Date(year, month, day, parseInt(timeParts[0], 10), parseInt(timeParts[1], 10), parseInt(timeParts[2], 10));
// Capture the current date/time as the baseline for both past-date and lead-time validations
var now = new Date();
// VALIDATION #1: Communications cannot be scheduled in the past
if (selectedDate.getTime() < now.getTime()) {
alert(pastMsg);
g_form.setValue('time_to_send_out_comms', ''); //Clear the variable value
return; // Stop processing further code
}
// VALIDATION #2: Communications cannot be scheduled on non-working days (Friday or Saturday)
// getDay() returns 0=Sunday, 1=Monday, 2=Tuesday, 3=Wednesday, 4=Thursday, 5=Friday, 6=Saturday
var selectedDayOfWeek = selectedDate.getDay();
if (selectedDayOfWeek === 5 || selectedDayOfWeek === 6) {
alert(weekendMsg);
g_form.setValue('time_to_send_out_comms', ''); //Clear the variable value
return; // Stop processing further code
}
// VALIDATION #3: Calculate the earliest allowed date/time by starting from the current moment and adding 2 working days while preserving the exact time (hour-based comparison)
var minDate = new Date(now.getTime());
// Track how many valid working days have been counted toward the 2-day minimum
var workingDaysAdded = 0;
// Iterate day-by-day until exactly 2 working days (Sunday–Thursday) have been accumulated
while (workingDaysAdded < 2) {
// Advance the date by one calendar day for each iteration
minDate.setDate(minDate.getDate() + 1);
// Determine if the current day in the loop is a working day or a non-working day
var dayOfWeek = minDate.getDay();
// Skip Friday (5) and Saturday (6) as they are defined as non-working days per business requirements
if (dayOfWeek !== 5 && dayOfWeek !== 6) {
// Count only valid working days toward the 2-day lead time requirement
workingDaysAdded++;
}
}
// Selected date/time must be at or after the same hour/minute/second on the 2nd working day from now
if (selectedDate.getTime() < minDate.getTime()) {
alert(leadMsg);
g_form.setValue('time_to_send_out_comms', ''); //Clear the variable value
return; // Stop processing further code
}
}
Validation Results:
Hope that helps!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hello @Sirri
Try this in your PDI first and find out if you are facing any issue or not. If not, then it means that your catalog item have something already which needs to be looked upon:
onChange Client script:
function onChange(control, oldValue, newValue, isLoading) {
//Stop processing further code from running when the form initially loads with pre-existing values
if (isLoading) {
return;
}
// Stop processing further code from running when user clears the field, as there is nothing to validate
if (!newValue || newValue == '') {
return;
}
var pastMsg = "The time chosen to send out the communication occurs in the past, kindly select a future date/time to proceed.";
var leadMsg = "Please allow two working days lead time for approvals and content review.";
var weekendMsg = "Communications cannot be scheduled on a Friday or Saturday as these are non-working days. Please select a working day (Sunday–Thursday).";
// Month abbreviation to 0-indexed number mapping for display-style format (e.g., "11/May/2026 10:41:26")
var monthMap = {
'Jan': 0, 'Feb': 1, 'Mar': 2, 'Apr': 3,
'May': 4, 'Jun': 5, 'Jul': 6, 'Aug': 7,
'Sep': 8, 'Oct': 9, 'Nov': 10, 'Dec': 11
};
// Required to separate the date component from the time component for independent parsing
var dateParts = newValue.split(' ');
// Required to extract hour, minute, and second as separate values from the time string like "12:48:24"
var timeParts = dateParts[1].split(':');
var year, month, day;
//Please go through below links to understand below code:
/*
indexOf(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf
split(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
parseInt(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
Date(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
*/
// For Date Time format: "11/May/2026 10:41:26"
if (dateParts[0].indexOf('/') !== -1) { // check whether date contain a forward slash
// Display-style format: "11/May/2026"
var dateComponents = dateParts[0].split('/'); // Splits "11/May/2026" into pieces: ["11", "May", "2026"]
day = parseInt(dateComponents[0], 10); // First piece "11" which is day = 11
month = monthMap[dateComponents[1]]; // Second piece "May" → look up in monthMap → month = 4 (0-indexed)
year = parseInt(dateComponents[2], 10); // Third piece "2026" → year = 2026
} else {
//For Date Time format: "2026-05-20" -- You can comment this if you don't need it.
var dateComponents = dateParts[0].split('-');
year = parseInt(dateComponents[0], 10);
month = parseInt(dateComponents[1], 10) - 1;
day = parseInt(dateComponents[2], 10);
}
// Required to construct a valid JavaScript Date; month is 0-indexed (0=Jan, 11=Dec)
var selectedDate = new Date(year, month, day, parseInt(timeParts[0], 10), parseInt(timeParts[1], 10), parseInt(timeParts[2], 10));
// Capture the current date/time as the baseline for both past-date and lead-time validations
var now = new Date();
// VALIDATION #1: Communications cannot be scheduled in the past
if (selectedDate.getTime() < now.getTime()) {
alert(pastMsg);
g_form.setValue('time_to_send_out_comms', ''); //Clear the variable value
return; // Stop processing further code
}
// VALIDATION #2: Communications cannot be scheduled on non-working days (Friday or Saturday)
// getDay() returns 0=Sunday, 1=Monday, 2=Tuesday, 3=Wednesday, 4=Thursday, 5=Friday, 6=Saturday
var selectedDayOfWeek = selectedDate.getDay();
if (selectedDayOfWeek === 5 || selectedDayOfWeek === 6) {
alert(weekendMsg);
g_form.setValue('time_to_send_out_comms', ''); //Clear the variable value
return; // Stop processing further code
}
// VALIDATION #3: Calculate the earliest allowed date/time by starting from the current moment and adding 2 working days while preserving the exact time (hour-based comparison)
var minDate = new Date(now.getTime());
// Track how many valid working days have been counted toward the 2-day minimum
var workingDaysAdded = 0;
// Iterate day-by-day until exactly 2 working days (Sunday–Thursday) have been accumulated
while (workingDaysAdded < 2) {
// Advance the date by one calendar day for each iteration
minDate.setDate(minDate.getDate() + 1);
// Determine if the current day in the loop is a working day or a non-working day
var dayOfWeek = minDate.getDay();
// Skip Friday (5) and Saturday (6) as they are defined as non-working days per business requirements
if (dayOfWeek !== 5 && dayOfWeek !== 6) {
// Count only valid working days toward the 2-day lead time requirement
workingDaysAdded++;
}
}
// Selected date/time must be at or after the same hour/minute/second on the 2nd working day from now
if (selectedDate.getTime() < minDate.getTime()) {
alert(leadMsg);
g_form.setValue('time_to_send_out_comms', ''); //Clear the variable value
return; // Stop processing further code
}
}
Validation Results:
Past Date:
Current Date Time:
Upcoming Weekend:
Next Friday: May 22nd
Next Saturday: May 23rd
Any future Friday:
Any furture Saturday:
Eligible day:
Hope that helps!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 weeks ago
Hi @Sirri
You can try this:
1) This onChange Client script triggers when the user changes the date/time field. It performs the "Past Date" check immediately and then validates the lead time via the Script Include.
Type: onChange
Variable name: communication_date // Replace with your field name
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
var selectedDate = new Date(getDateFromFormat(newValue, g_user_date_time_format));
var today = new Date();
if (selectedDate < today) {
g_form.clearValue('communication_date'); // Replace with your field name
g_form.showFieldMsg('communication_date', 'The time chosen to send out the communication occurs in the past, kindly select a future date/time to proceed.', 'error');
return;
}
var ga = new GlideAjax('DateTimeValidationUtils');
ga.addParam('sysparm_name', 'getMinLeadTimeDate');
ga.getXMLAnswer(function(answer) {
var minAllowedDate = new Date(getDateFromFormat(answer, "yyyy-MM-dd HH:mm:ss"));
if (selectedDate < minAllowedDate) {
g_form.clearValue('communication_date'); // Replace with your field name
g_form.showFieldMsg('communication_date', 'Please allow two working days lead time for approvals and content review.', 'error');
}
});
}
2) This script Include calculates the minimum allowed date based on the "2 Working Days" rule (Sunday to Thursday).
Name: DateTimeValidationUtils
Client callable: Checked
var DateTimeValidationUtils = Class.create();
DateTimeValidationUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getMinLeadTimeDate: function() {
var now = new GlideDateTime();
var daysAdded = 0;
while (daysAdded < 2) {
now.addDaysLocalTime(1);
var dayOfWeek = now.getDayOfWeekLocalTime();
// ServiceNow getDayOfWeek: 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri, 6=Sat, 7=Sun
// Your Working Days: Sun (7) to Thu (4). Non-working: Fri (5), Sat (6)
if (dayOfWeek != 5 && dayOfWeek != 6) {
daysAdded++;
}
}
return now.getValue(); // Returns yyyy-MM-dd HH:mm:ss
},
type: 'DateTimeValidationUtils'
});
Regards
Tanushree Maiti
ServiceNow Technical Architect
LinkedIn: https://www.linkedin.com/in/tanushreemaiti
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
a week ago
Hey Sirri,
I have implemented an onChange Catalog Client Script for the `time_to_send_out_comms` Date/Time variable to satisfy two business requirements:
1. User should not be allowed to select a past date/time.
2. User should provide a minimum lead time of 2 working days.
Working days considered are Sunday to Thursday, and Friday/Saturday are treated as non-working days.
Script explanation:
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
// Current Date date
var now = new Date();
// User selected date/time
var selectedDate = new Date(newValue);
// Validate past date
if (selectedDate < now) {
alert('Please select a future date and time.');
g_form.clearValue('time_to_send_out_comms');
return;
}
// Calculate minimum allowed date
var minDate = new Date(now);
var workingDays = 0;
//The purpose of this loop is to move forward day by day until two working days are identified.
while (workingDays < 2) {
minDate.setDate(minDate.getDate() + 1);
var day = minDate.getDay();
if (day >= 0 && day <= 4) {
workingDays++;
}
}
if (selectedDate < minDate) {
alert('Please allow two working days lead time for approvals and content review.');
g_form.clearValue('time_to_send_out_comms');
}
}