Catalog variable Date/Time validation – 2 working days (Sun–Thu) with hour‑based lead time

Sirri
Tera Guru

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 Requirement

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

    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.

    Thank you

     





1 ACCEPTED SOLUTION

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

VishalJaswal_0-1778855253994.png



Validation Results:

VishalJaswal_1-1778855289743.png

VishalJaswal_2-1778855302986.png

 

VishalJaswal_3-1778855313382.pngVishalJaswal_4-1778855323279.png

VishalJaswal_5-1778855335437.png

 




Hope that helps!

View solution in original post

27 REPLIES 27

Ankur Bawiskar
Tera Patron

@Sirri 

approach

-> use onChange catalog client script and 1st check if value is in past then show error

-> if date is not in past then check business days

see this link for solution and enhance

Variable Date no less than 5 business days 

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

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

Hi @Ankur Bawiskar ,

Thank you for your response. Please can you share exact code as per my requirement. It will be helpful to me.

Thank you

@Sirri 

the link I shared already has a working solution, you need to enhance it as per your requirement.

💡 If my response helped, please mark it as correct and close the thread 🔒— this helps future readers find the solution faster! 🙏

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

Vishal Jaswal
Tera Sage

Hello @Sirri 

To achieve this, please use below onChange Catalog 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.";

    // Required to separate the date component from the time component for independent parsing -- ServiceNow date/time variable stores value as "2026-05-20 12:48:24"
    var parts = newValue.split(' ');

    // Required to extract year, month, and day as separate values from the date string like "2026-05-20"
    var d = parts[0].split('-');

    // Required to extract hour, minute, and second as separate values from the time string like "12:48:24"
    var t = parts[1].split(':');

    // Required to construct a valid JavaScript Date; month is decremented by 1 because JavaScript months are 0-indexed (0=Jan, 11=Dec)
    var selected = new Date(parseInt(d[0], 10), parseInt(d[1], 10) - 1, parseInt(d[2], 10), parseInt(t[0], 10), parseInt(t[1], 10), parseInt(t[2], 10));

    // Capture the current date/time as the baseline for both past-date and lead-time validations
    var now = new Date();

    // Communications cannot be scheduled in the past
    if (selected.getTime() < now.getTime()) {
        alert(pastMsg);
        g_form.setValue('time_to_send_out_comms', ''); //Clear the variable value
        return; // Stop processing further code
    }

    // 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 (selected.getTime() < minDate.getTime()) {
        alert(leadMsg);
        g_form.setValue('time_to_send_out_comms', ''); //Clear the variable value       
        return; // Stop processing further code
    }
}


Validation Results:
When Selected Yesterday:

VishalJaswal_0-1778702135937.png



When Selected current or future Date which is less than 2 working days:

VishalJaswal_1-1778702169812.pngVishalJaswal_2-1778702181248.png

VishalJaswal_0-1778702295437.png

 


When future date allowing 2 working days is selected:
VishalJaswal_3-1778702192588.png

 




Hope that helps!