ServiceNow – Automating Bank Holidays (U.K.)

I wanted to share this potentially useful tip related to ServiceNow schedules. There might be instances when you need to use schedules, such as managing SLAs that should only trigger during work hours.

Setting up schedules is generally straightforward, but sometimes you need to exclude specific dates like bank holidays. The UK government has provided a JSON formatted list of UK bank holidays, accessible here:

https://www.api.gov.uk/gds/bank-holidays/#bank-holidays

This resource is really useful for populating bank holidays automatically. I created a new schedule, populate it with entries from the JSON data, and then referenced this schedule. If you’d like to use the same approach, here’s the script I used. You only need to replace ‘schedule_sys_id’ with the sys_id of your new schedule.

// SysID of the schedule to be updated
var schedule_sys_id = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; 

// Create a new instance of RESTMessageV2 for HTTP requests
var request = new sn_ws.RESTMessageV2();

// Set the endpoint of the HTTP request
request.setEndpoint('https://www.gov.uk/bank-holidays.json');

// Set the method to GET to fetch data
request.setHttpMethod('GET');

// Set the header to accept application/json
request.setRequestHeader("Accept","application/json");

// Execute the HTTP request and store the response
var response = request.execute();
gs.info('HTTP request sent to fetch bank holidays');

// Get the response body
var str = response.getBody();

// Parse the JSON string into a JavaScript object
var obj = JSON.parse(str);

// Extract the list of holidays for England and Wales
var ukHolidays = obj['england-and-wales'].events;
gs.info('Fetched ' + ukHolidays.length + ' UK bank holidays');

// Loop over each bank holiday
for (var bankHoliday in ukHolidays) {
	// Check if the current property belongs to the object itself
	if(!ukHolidays.hasOwnProperty(bankHoliday)) continue;
	
	// Extract the title, date, and notes of the bank holiday
	var title = ukHolidays[bankHoliday].title;
	var date = ukHolidays[bankHoliday].date;
	var notes = ukHolidays[bankHoliday].notes;

	// Convert the date into a GlideDateTime object
	var gdt = new GlideDateTime(date);
	
	// Query the 'cmn_schedule_span' table to check if the record already exists
	var checkFirst = new GlideRecord('cmn_schedule_span');
	checkFirst.addQuery('schedule', schedule_sys_id);
	checkFirst.addQuery('name',(title + ' - ' + gdt.getYearUTC()));
	checkFirst.query();
	
	// If the record doesn't exist, create a new one
	if (!checkFirst.hasNext()){
		var gr = new GlideRecord('cmn_schedule_span');
		gr.initialize();
		gr.schedule = schedule_sys_id;
		gr.name = (title + ' - ' + gdt.getYearUTC());
		gr.type = 'exclude';
		gr.show_as = 'busy';
		gr.all_day = true;
		gr.start_date_time = gdt.getDate().toString();
		gdt.addDays(1);
		gr.end_date_time = gdt.getDate().toString();
		gr.notes = notes;
		gr.insert();
		gs.info('Added bank holiday: ' + title + ' - ' + gdt.getYearUTC());
	} else {
		gs.warn('Bank holiday already exists in the schedule: ' + title + ' - ' + gdt.getYearUTC());
	}
}

ChatGPT – Truncation of Responses

ChatGPT has already proven to be an incredibly powerful tool. People are launching phenomenal projects with it, showcasing its potential as a transformative technology. Some have even referred to it as the “iPhone moment” for AI, and I can’t help but agree.

That being said, like any tool, it does have its quirks. One common issue is the truncation of responses. For instance, while generating code, ChatGPT might abruptly cut off, prompting you to “regenerate response” and leading to the repetition of the same text.

If you encounter this, there are strategies to mitigate it. One simple method is to prompt the model with:

“Please continue.”

This command typically gets ChatGPT to carry on from where it left off. However, it’s worth noting that there can be peculiarities with this approach. If the AI halts during a code block, it may resume the code but not within the same code block.

A more effective workaround I’ve found involves pinpointing the most recent function it began to write (or any line of code you want to continue from) and instructing it to:

“Please continue from function [function name] onwards.”

This method usually results in the continuation of the code within a proper code block.

TradingView – Cannot use ‘barcolor’ in local scope

Ran into this issue a few times when trying to set the bar or background colour in a pine script. Its a relatively simple fix, but it can trip you up the first time you see it.

For example, this is a super simple RSI script. I’m attempting to set the bar colour if the RSI value is above 80:

//@version=5
indicator(shorttitle="RSI Script", title="Simple RSI Script", overlay = false)
length = input(14, title="RSI Period")
overBought = input(70, title="Overbought Level")
overSold = input(30, title="Oversold Level")

rsiValue = ta.rsi(close, length)

plot(rsiValue, title="RSI", color=color.blue)
hline(overBought, title="Overbought Level", color=color.red)
hline(overSold, title="Oversold Level", color=color.green)

if (rsiValue > 80)
    barcolor(color=color.red)

However, if I try to add this script to the chart I get the error “Cannot use ‘barcolor’ in local scope”.

To get around this, remove the if statement and use something like the following:

myColour = (rsiValue > 80) ? color.purple : na
barcolor(color=myColour)

Effectively this either sets the bar colour to purple if RSI value is above 80, or na if it’s not. Full script below for clarity:

//@version=5
indicator(shorttitle="RSI Script", title="Simple RSI Script", overlay = false)
length = input(14, title="RSI Period")
overBought = input(70, title="Overbought Level")
overSold = input(30, title="Oversold Level")

rsiValue = ta.rsi(close, length)

plot(rsiValue, title="RSI", color=color.blue)
hline(overBought, title="Overbought Level", color=color.red)
hline(overSold, title="Oversold Level", color=color.green)

myColour = (rsiValue > 80) ? color.purple : na
barcolor(color=myColour)