Skip to Content

Custom Date Range Validation

Validate date fields against each other with custom business rules like working days, blackout periods, and lead times.

onChange Table: change_request Field: start_date
#onChange #date-validation #business-rules #blackout-dates #lead-time #change-management

Script Code

JavaScript
1function onChange(control, oldValue, newValue, isLoading, isTemplate) {
2  // Exit if form is loading
3  if (isLoading) {
4    return;
5  }
6
7  // Configuration
8  var minimumLeadTimeDays = 3;  // Minimum days in advance
9  var minimumDurationHours = 1;  // Minimum change window
10  var maximumDurationHours = 8;  // Maximum change window
11
12  // Blackout periods (no changes allowed)
13  var blackoutPeriods = [
14    {start: '2024-12-24', end: '2024-12-26', reason: 'Holiday Freeze'},
15    {start: '2024-12-31', end: '2025-01-02', reason: 'New Year Freeze'}
16  ];
17
18  // Restricted days (require additional approval)
19  var restrictedDays = [0, 6];  // Sunday = 0, Saturday = 6
20
21  // Get both date fields
22  var startDate = g_form.getValue('start_date');
23  var endDate = g_form.getValue('end_date');
24
25  // Clear previous messages
26  g_form.hideFieldMsg('start_date');
27  g_form.hideFieldMsg('end_date');
28
29  if (!startDate) {
30    return;
31  }
32
33  var start = new Date(startDate);
34  var now = new Date();
35
36  // Validation 1: Check minimum lead time
37  var leadTimeMs = start - now;
38  var leadTimeDays = leadTimeMs / (1000 * 60 * 60 * 24);
39
40  if (leadTimeDays < minimumLeadTimeDays) {
41    var message = 'Start date must be at least ' + minimumLeadTimeDays + 
42                  ' days in advance. Current lead time: ' + 
43                  leadTimeDays.toFixed(1) + ' days.';
44    g_form.showFieldMsg('start_date', message, 'error');
45    g_form.addErrorMessage(message);
46  }
47
48  // Validation 2: Check if date is in the past
49  if (start < now) {
50    g_form.showFieldMsg('start_date', 'Start date cannot be in the past', 'error');
51  }
52
53  // Validation 3: Check blackout periods
54  for (var i = 0; i < blackoutPeriods.length; i++) {
55    var blackout = blackoutPeriods[i];
56    var blackoutStart = new Date(blackout.start);
57    var blackoutEnd = new Date(blackout.end);
58
59    if (start >= blackoutStart && start <= blackoutEnd) {
60      var message = 'Change cannot be scheduled during ' + blackout.reason + 
61                   ' (' + blackout.start + ' to ' + blackout.end + ')';
62      g_form.showFieldMsg('start_date', message, 'error');
63      g_form.addErrorMessage(message);
64    }
65  }
66
67  // Validation 4: Check restricted days (weekends)
68  var dayOfWeek = start.getDay();
69  if (restrictedDays.indexOf(dayOfWeek) !== -1) {
70    var dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 
71                    'Thursday', 'Friday', 'Saturday'];
72    var message = 'Changes scheduled on ' + dayNames[dayOfWeek] + 
73                 ' require additional approval';
74    g_form.showFieldMsg('start_date', message, 'warning');
75    g_form.addInfoMessage(message);
76    
77    // Set flag for additional approval requirement
78    g_form.setValue('u_requires_additional_approval', 'true');
79  }
80
81  // Validation 5: Check business hours (e.g., 9 AM - 5 PM)
82  var hour = start.getHours();
83  var isBusinessHours = (hour >= 9 && hour < 17);
84  
85  if (!isBusinessHours) {
86    g_form.showFieldMsg('start_date', 
87                       'After-hours change: Additional approval may be required', 
88                       'warning');
89  }
90
91  // Validation 6: Validate against end date if present
92  if (endDate) {
93    var end = new Date(endDate);
94
95    // End must be after start
96    if (end <= start) {
97      g_form.showFieldMsg('end_date', 'End date must be after start date', 'error');
98    } else {
99      // Check duration
100      var durationMs = end - start;
101      var durationHours = durationMs / (1000 * 60 * 60);
102
103      if (durationHours < minimumDurationHours) {
104        var message = 'Change window must be at least ' + 
105                     minimumDurationHours + ' hour(s)';
106        g_form.showFieldMsg('end_date', message, 'error');
107      }
108
109      if (durationHours > maximumDurationHours) {
110        var message = 'Change window exceeds maximum of ' + 
111                     maximumDurationHours + ' hours. ' +
112                     'Consider breaking into multiple changes.';
113        g_form.showFieldMsg('end_date', message, 'warning');
114      }
115
116      // Show duration info
117      var durationInfo = 'Change window: ' + durationHours.toFixed(1) + ' hours';
118      g_form.showFieldMsg('end_date', durationInfo, 'info');
119    }
120  }
121
122  // Validation 7: Check for conflicts with other changes
123  // This would require GlideAjax call to check server-side
124  // Simplified example:
125  /*
126  var ga = new GlideAjax('ChangeConflictChecker');
127  ga.addParam('sysparm_name', 'checkConflicts');
128  ga.addParam('sysparm_start_date', startDate);
129  ga.addParam('sysparm_end_date', endDate);
130  ga.addParam('sysparm_ci', g_form.getValue('cmdb_ci'));
131  
132  ga.getXMLAnswer(function(response) {
133    if (response === 'true') {
134      g_form.showFieldMsg('start_date', 
135                         'Warning: Another change is scheduled during this time', 
136                         'warning');
137    }
138  });
139  */
140}

How to Use

1. Create onChange Client Scripts for both start_date and end_date fields 2. Customize minimumLeadTimeDays and duration limits for your policies 3. Update blackoutPeriods array with your freeze dates 4. Adjust restrictedDays for your organization (weekends, specific days) 5. Create duplicate script for end_date field 6. Consider adding GlideAjax call for conflict checking 7. Test all date scenarios including edge cases 8. Document validation rules for users

Explore More Scripts

Browse our complete library of ServiceNow scripts

View All Scripts