Add UK Bank Holidays to Teams Voice

If you have ever administered a Phone System you will know that one of the most boring tasks you can be asked to do, is program in the new years bank holiday dates. Even today one of the most popular phone systems on the market 3CX it remains a manual task.

With Microsoft Teams Voice you of course benefit from a PowerShell interface to configure your system, and if we combine this with a surprisingly useful part of the gov.uk website we can can programmatically get, and input our bank holiday dates for the year ahead. In fact the current document has dates through to the end of 2026.

To do this we will make use of New-CsOnlineDateTimeRange, New-CsOnlineSchedule and Set-CsOnlineSchedule which are part of the Microsoft Teams PowerShell module.

I have provided a link at the end of the post where you can download the script, but I know people like to see an explanation of how these things are put together and that follows below.

The page that makes this possible is here, https://www.gov.uk/bank-holidays.json

So, in our script our first task is going to be to grab that JSON content and store it.

$dates = (Invoke-Restmethod https://www.gov.uk/bank-holidays.json -ContentType "application/json") 

This will grab all the dates from the page and store them in the $dates variable.

We will then initialise some other variables.

$currentDate = [datetime]::Now.date 
$engWalDates = $dates.'england-and-wales'.events
$scotDates = $dates.'scotland'.events
$niDates = $dates.'northern-ireland'.events
$dateObjs = New-Object System.Collections.ArrayList

These store the current date, which we will use to work out which events are coming up and which have passed, and the separate countries of the UK then lastly an array list to store our converted date ranges before adding to Teams.

In the next section I have added an array to filter which countries events to include, reason for this is whilst Scotland may celebrate a Bank Holiday, you may not actually close your offices and this allows a bit of flexibility on that.

$useDates = @(
    $engWalDates
    #$scotDates # commented out for Scotland
    #$niDates # commented out for Northern Ireland
)

In the example code above I am choosing to only process dates for England and Wales.

Next we have a foreach loop, which will process each date in $engWalDates and convert it to a PowerShell custom object, which includes the Bank Holiday name, the start and end date (Start Date + 1 day) and the year as a separate property.

foreach ($date in $useDates){
    $start = Get-Date $date.date
    $year = $start.Year
    if(($start) -ge $currentDate){
        $dateObj = [pscustomObject]@{
            Name = $date.title
            Start = $start
            End = $start.adddays(1) 
            Year = $year
        }
        $dateCheck = $dateObjs | Where-Object { ($_.Name -eq $dateObj.name) -and ($_.Start -eq $dateobj.start) } # look for duplicate dates
        if(!($dateCheck)){
            $dateObjs.add($dateObj) | Out-Null
        }
        else{
            Write-Output "Duplicate Date : $($dateObj.name)"
        }
    }
}
Example of a $dateObj after processing, the Boxing Day 2026 Bank Holiday is Monday the 28th December.

We then search our $dateObjs array list for an existing value of $dateObj, if no existing value is found we add $dateObj to $dateObjs.

The next task is to group each of our $dateObjs into years.

$years = $dateObjs | Group-Object Year 

$years will group $dateObjs objects by year.

We use $years in conjunction with New-CsOnlineSchedule to create a new Schedule for each year. We automatically add the Christmas shutdown to the schedule which defaults to the 25th and 26th of December.

We add the Christmas shutdown as a default, as creating a schedule requires at least one date to be added, and this seems like a sensible one to chose.

As you can see from the above example, we will create three new schedules. These will be named:

  • UK Bank Holidays – 2024
  • UK Bank Holidays – 2025
  • UK Bank Holidays – 2026

The script will loop through and again look for duplicates, or look for the names of holidays you have specifically chosen to exclude (for example you might choose to include Scotland, but still want to exclude St Andrews Day.

$skipDays = @(
    "Christmas Day"
    "Boxing Day"
    "St Andrew’s Day"
    "St Patrick’s Day"
)

A $hol object is created with New-CsOnlineDateTimeRange using the start and end date we calculated earlier. We then add the $hol object to our schedule using the Set-CsOnlineSchedule command.

$hol = New-CsOnlineDateTimeRange -Start $holiday.start.date.ToString().split(" ")[0] -End $holiday.end.date.toString().split(" ")[0]
# check for duplicate dates
$schedule.FixedSchedule.DateTimeRanges += $hol
Set-CsOnlineSchedule -Instance $schedule

If we add all this together what do we get?

<truncated the image>

In the Teams Admin Centre we can now see our Bank Holiday schedules available and ready for use in call flows.

Now, I know what you’re thinking why just the UK?

To which I say, why not?

I did do some research while initially writing this script and found inconsistent results for other countries public holidays being shared via API until I found this website, https://openholidaysapi.org

Using this site, and some parameters we can extend our script to include most countries in Europe.

For example, France for years 2024-2026..

$countryCode = "FR"
$startYear = 2024
$endYear = 2026
$dateObjs = New-Object System.Collections.ArrayList
$dates = Invoke-RestMethod -uri "https://openholidaysapi.org/PublicHolidays?countryIsoCode=$countryCode&languageIsoCode=GB&validFrom=$startYear-01-01&validTo=$endYear-12-31" -ContentType "application/json"
if($dates){
    foreach ($date in $dates){
        $dateObj = [pscustomObject]@{
            Name = $date.name.text
            Start = Get-Date $date.startdate
            End = (get-date $date.endDate).AddDays(1) 
            Year = (Get-Date $date.startdate).year
        }
        $dateObjs.add($dateObj) | Out-Null
    }
    $years = $dateObjs | Group-Object Year 
}    
$years[1].group
Looking at 2025 French public holidays.

Unfortunately, the OpenHolidaysAPI site does not include the UK so you will need to query both URLs if you need holidays for mainland europe.

You can download both scripts from my GitHub page.

Thanks to Adam Bamping for his assistance with Teams Voice!

Unknown's avatarAbout Robert Pearman
Robert Pearman is a UK based IT worker bee. He has been working within the IT Industry for what feels like forever. Robert likes Piña colada and getting caught in the rain, he also enjoys writing about Technology like PowerShell or System Automation but not as much as he used to. If you're in trouble, and you can find him, maybe you can ask him a question.

Leave a reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.