
- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 04-30-2021 01:25 PM
We've run into a number of cases where we would like scheduled jobs to run at specific times of day on specific days of the week. This condition script will make it very simple to define which times of day and/or days of week you want your scheduled job to run.
To use this script:
- Set the schedule job to RUN: Periodically
- Set the REPEAT INTERVAL to 0 Days, 1 Hours (this causes the script to check whether it should run once every hour)
- Check the CONDITIONAL box
- Copy and paste the entire script below into the CONDITION script
- Update the "runHours" and "runWeekdays" variables in the script as follows:
runHours: Which hour(s) of the day should the job run? Can be one or multiple values.
Examples:
runHours = [9] //Only send at 9 am
runHours = [0, 13] //Run at midnight and 1 pm
runHours = [8, 12, 17] //Run at 8 am, 12 pm, 5 pm
runWeekdays: Which days of the week should the job run? Can be one or multiple values. (Monday = 1, Tuesday = 2... Sunday = 7)
Examples:
runWeekdays = [1, 2, 3, 4, 5] //Run on weekdays - Mon through Fri
runWeekdays = [1, 3, 5] //Run Mon, Wed, Fri
runWeekdays = [6, 7] //Run Sat & Sun
//Use Run: Periodically, Interval: 1 hour (check conditions every hour - send if appropriate)
(function () {
var runHours = [9, 14, 16]; //Hour of day to send (24 hour time)
var runWeekdays = [1, 2, 3, 4, 5]; //Days of week - (Mon = 1, Tues = 2... Sun = 7)
var answer = false; //Default to false
var shouldRunToday = checkRunWeekday(runWeekdays);
var shouldRunThisHour = checkRunHour(runHours);
if (shouldRunToday && shouldRunThisHour) answer = true;
return answer;
})();
function checkRunWeekday(runDays) {
//Return true if we should send today. Otherwise, return false
var currentDayOfWeek = getCurrentDayOfWeek();
if (runDays.indexOf(currentDayOfWeek) > -1) return true;
return false;
}
function getCurrentDayOfWeek() {
var gdt = new GlideDateTime();
var dayOfWeek = gdt.getDayOfWeekLocalTime();
return dayOfWeek;
}
function checkRunHour(runHours) {
//Return true if we should send this hour. Otherwise, return false
var hour = getCurrentHour();
if (runHours.indexOf(hour) > -1) return true;
return false;
}
function getCurrentHour() {
var gt = new GlideTime();
var hour = gt.getHourOfDayLocalTime();
return hour;
}
Note that this uses "local" time. Make sure you test and adjust as appropriate. I believe time zone is decided based on the "Run As" user of the scheduled job.
Author note: I've written the script to be easy to read/parse. It could easily be consolidated down to a few lines of code, but I prefer to write "self documenting code" where possible.
- 7,781 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I have a requirement to run scheduled job every 15 minutes. Will the script work as-is if I set the REPEAT INTERVAL to 0 Days, 0 Hours, 15 minutes?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
EDIT: Hijacking my own highest comment:
New scripts have been posted that address script sandboxing issues with scheduled reports in the comments below.
----
I suppose it would depending on what exactly you're trying to do. Are you trying to make it so that the job only runs during business hours or something along those lines?
For example, if you set hours and days to:
var runHours = [8,9,10,11,12,13,14,15,16]; //Any time 8:00 AM through 4:59 PM
var runWeekdays = [1, 2, 3, 4, 5]; //Days of week - (Mon = 1, Tues = 2... Sun = 7)
That would tell the script condition that the job should run during those 1-hour blocks on Monday - Friday. If you run the job every 15 minutes, then 8:00, 8:15, 8:30, and 8:45 and so on would all evaluate to true on weekdays. The script only looks at day of week and hour to check if it should run, not minutes.
The idea was to give the script the flexibility in case you wanted it to run every day at say 8:30 am instead of just right at 8:00 am.
If there's no need to limit the job to specific time frames then you wouldn't need this script at all. Just set the job to run every 15 minutes as you described without any conditions.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Jon,
I am trying to run the job every 15 minutes between the hours of 6:30 AM and 8:30 AM ET every day.
Based on your fine script, I have it working but it starts at 6:00 AM and ends at 8:59 AM ET. I believe the solution will meet the requirement until I have time to figure out how to trigger it based on minutes.
Thank you,
Cyn

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I'm not sure if you've come up with a complete solution, but I was just looking back at this and thought I'd give it a go. Let me know if this works for you:
answer = (function () {
//Set start times in HH:mm format:
var startTime = '06:30';
var endTime = '08:30';
////////////////
startTime += ':00'; //add seconds since times above don't include seconds
var startGt = new GlideTime();
startGt.setValue(startTime);
endTime += ':00';
var endGt = new GlideTime();
endGt.setValue(endTime);
var gdt = new GlideDateTime();
var now = gdt.getLocalTime();
var afterStart = startGt < now;
var beforeEnd = now < endGt;
if(afterStart && beforeEnd) {
return true;
}
return false
})();
Run this on whatever interval you wish, and it should return "true" as long as the time is between the start and end times.
Since this is an article post, a brief explanation:
ServiceNow makes it pretty easy to compare times like this, but you have to be careful of some of the odd things they do. For example, setting a GlideTime object manually with .setValue() only has the time portion without the date. Or rather, date is set to 01-01-1970. However, when you first create a GlideTime object, the current date is included with the current time for some reason. That breaks simple comparisons like what we're trying to do here. For example (2022-07-10 07:00:00) is not between (1970-01-01 06:30:00) and (1970-01-01 08:30:00)
I work around that by using GlideDateTime to get the time. GDT is a little more useful here anyway because we can use "getLocalTime()". GlideTime does not have a get local time function on its own.
Hope this helps

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I hadn't implemented a full solution. Thank you so much for circling back to this. I really appreciate it.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Jon,
Great article! I'm having a bit of an issue though. I've copied and pasted your whole script and have only changed the var runHours = [9, 14, 16]; to "var runHours = [8, 12, 16];" and set the repeat interval to 1 hour as suggested. Unfortunately the report runs every hour and also sends a report every hour. Any suggestions?
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Great post but I'm having same issue as Josh - what are we missing?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
That's odd. I just tested in my dev instance and I'm seeing the same behavior now. It looks like something may have changed as of Orlando: https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0827366. My use case has been with scheduled jobs more often than reports, and it looks like this issue may apply specifically to reports. I suspect this is because users other than admins may be delegated permissions to schedule reports.
I'm going to mess with this a bit more to see if I can get it working again, but I'll need to check some more, particularly with considerations for time zones.
In the meantime, you could try replacing the following functions (not tested yet):
function getCurrentDayOfWeekNew() {
var d = new Date();
var dayOfWeek = d.getDay();
return dayOfWeek;
}
function getCurrentHour() {
var d = new Date();
var hour = d.getHours();
return hour;
}
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @Jon G1
I have impleted it, using your code as reference for minutes too.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thanks for sharing your solution @mrkr269 . Hopefully it saves someone a headache or two in the future.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Jon,
I have followed the instructions and tested it for two days. It does not work as expected.
I want the schedule to run twice a week, on Sunday and Wednesday at 7 p.m. I have modified the script to do that. Instead of running only at my predefined time, it runs every hour while I have set the Conditional to true.
I'm on Vancouver release, patch10-hotfix2.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
@Sri4 You should only need to set the times like this:
var runHours = [19]; //Hour of day to send (24 hour time)
var runWeekdays = [3,7]; //Days of week - (Mon = 1, Tues = 2... Sun = 7)
Note that some users found a discrepancy between the way Scheduled Jobs and Scheduled Report Generation seem to work in terms of what JavaScript functions are allowed. Can you let me know what kind of scheduled job you're creating? I'll test in my dev instance to see if there's something wrong.
And unfortunately, ServiceNow changed who is allowed to write articles so I can't even edit my own article with new information. Please make sure to review the comments above to see if any of those cases apply.
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Jon,
Yes, I did that as you suggested. It did not work for me.
I use it to generate a Scheduled Report.
I also noticed a possible script issue with your original one. I've used both the original from you and the one I modified, but none of them works for my scheduled report.
In your original script, you used "runWeekdays" on line 5 and 8, like this: "var runWeekdays = ..."
and
"var shouldRunToday = checkRunWeekday(runWeekdays)".
However, for the function, you used "rundays" (line 17) like this:
"function checkRunWeekday(runDays) {"
I initially used your version, and in my version I replaced all 'runWeekdays' with 'rundays'.
Both did not work. Any suggestion?

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi @Sri4 , Apologies I didn't see this sooner.
Taking the second question first, the use of different variable names was intentional. However, the use of functions at all was apparently the issue with the script not working in scheduled reports. I had assumed it was the GlideDateTime calls because of Script Sandboxing. But after a ton of testing, removing the function declarations seemed to make it work. I'll post fixed scripts right after this post. There are tons of people complaining about this apparently unexpected behavior. One of those posts mentions the limitations on the use of functions citing the script sandboxing documentation, but that particular doc no longer mentions that assuming that's where they got it from.
Admittedly, as I mentioned in the note at the bottom of the article, this whole script design with all its functions was overkill. It was intended to be more of a teaching tool to explain what it was doing by breaking things down into smaller bites with the hopes that people who come through to see how a somewhat complex problem can be broken down into smaller chunks.
To explain the use of different variable names, I did that because I wanted to split everything up into separate scopes to make it more clear how these individual parts of the script fit together. Scopes are sort of like containers that define limits to where variables can be accessed from. Each function has its own scope. On a script this short, it isn't really necessary, but on longer scripts it can save you a lot of headaches.
The very first function is an Immediately Invoked Function Expression or IIFE. All of the code in that block is separated from the other functions which takes the variables defined there out of the global scope. Variables created in the global scope (outside of all the functions) could be unintentionally referenced or overwritten. That's because variables declared with the "var" statement in the global scope are accessible to the functions declared below global - which is I think what you were expecting.
So in the bits of code you referenced, I declare the variable "runWeekdays" as the array within the initial IIFE. On the next line, I also declare the variable "shouldRunToday" which will accept the value returned from the "checkRunWeekday" function. The data that I'm passing into that function is the "runWeekdays" variable which I just defined on the previous line.
The function being called is declared as "function checkRunWeekday(runDays)". When you create a function, whatever is in the parenthesis is essentially declaring a variable to be used as an input parameter for the function. Here I declared the input as "runDays". That runDays variable is only accessible within that function, and the variable will contain whatever information was passed when the function was called.
Here's another way to look at it. Let's get rid of the "runWeekdays" variable altogether. Now we are calling the function with something like this:
(function () {
var shouldRunToday = checkRunWeekday([1, 2, 3, 4, 5]);
})();
In this case, we haven't defined any variable, but we still need to work with those values inside the function. That's where "runDays" comes in to play.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Updated Scripts - Try these if you're having trouble
ServiceNow has a "Script Sandboxing" feature that severely limits what can be done in certain script fields, including the condition field on Scheduled Reports. Those limitations include the use of GlideDateTime and GlideTime methods that my original script relied upon. There's also apparently a restriction on the use of functions for some reason. It took me quite a while to track down the offending components, but I've got two versions of the script that seem to be working.
Pure JavaScript version
The script below does not rely on any ServiceNow-native classes. Not being able to use the GlideDateTime and GlideTime functions is not ideal because you lose their built-in time zone handling features. This is the best that I could come up with that maintains the spirit of the original script while streamlining the code. Note that you have to manually specify your timezone offset and will have to update it for DST:
// JavaScript version
// Use Run: Periodically, Interval: 1 hour (check conditions every hour - send if appropriate)
var tzOffset = -6;
// Note that you must manually define your Timezone offset and will need to update it for DST
// I welcome contributions if anyone has a good way to handle DST & time zones better than this, but that's beyond the scope of this article
var runHours = [9, 14, 16, 21]; //Hour of day to send (24 hour time)
var runWeekdays = [1, 2, 3, 4, 5]; //Days of week - (Mon = 1, Tues = 2... Sun = 7)
var d = new Date();
var offsetHour = d.getUTCHours() + tzOffset;
var utcDay = d.getUTCDay();
var dayOfWeek = offsetHour >= 0 ? utcDay : utcDay - 1;
var shouldRunToday = runWeekdays.indexOf(dayOfWeek) > -1;
var hour = new Date().getUTCHours();
hour = hour + tzOffset;
hour = hour < 0 ? hour + 24 : hour;
hour = hour > 24 ? hour - 24 : hour;
var shouldRunThisHour = runHours.indexOf(hour) > -1;
answer = shouldRunToday && shouldRunThisHour;
ServiceNow GLIDE version
According to the script sandboxing documentation, this shouldn't work due to the use of GlideDateTime and GlideTime. However, it seemed to work in my limited testing, so I'll post it here in case anyone wants to play with it
// GLIDE version:
// Use Run: Periodically, Interval: 1 hour (check conditions every hour - send if appropriate)
// Settings
var runHours = [9, 14, 16]; //Hour of day to send (24 hour time)
var runWeekdays = [1, 2, 3, 4, 5]; //Days of week - (Mon = 1, Tues = 2... Sun = 7)
// Get day of week
var gdt = new GlideDateTime();
var dayOfWeek = gdt.getDayOfWeekLocalTime();
// Get current hour
var gt = new GlideTime();
var hour = gt.getHourOfDayLocalTime();
// Evaluate
var shouldRunToday = runWeekdays.indexOf(dayOfWeek) > -1;
var shouldRunThisHour = runHours.indexOf(hour) > -1;
answer = shouldRunToday && shouldRunThisHour;