Holidays

UK Bank Holidays Calculator

England and Wales's bank holidays for any year, calculated live — including substitute days when a fixed holiday falls on a weekend.

England and Wales, specifically

The UK doesn't have one single bank holiday calendar — Scotland and Northern Ireland each observe a different set. Scotland skips Easter Monday but keeps St Andrew's Day (November 30) and observes its summer bank holiday on the first Monday of August rather than the last. Northern Ireland adds both St Patrick's Day (March 17) and Orangemen's Day (July 12). This calculator shows the England and Wales calendar specifically.

The substitute-day rule

When a fixed-date bank holiday (New Year's Day, Christmas, Boxing Day) falls on a weekend, the next available weekday becomes a substitute bank holiday — shown below wherever it applies.

Related

Related tools

function computeEaster(year){ const a = year % 19; const b = Math.floor(year/100); const c = year % 100; const d = Math.floor(b/4); const e = b % 4; const f = Math.floor((b+8)/25); const g = Math.floor((b-f+1)/3); const h = (19*a + b - d - g + 15) % 30; const i = Math.floor(c/4); const k = c % 4; const l = (32 + 2*e + 2*i - h - k) % 7; const m = Math.floor((a + 11*h + 22*l)/451); const month = Math.floor((h + l - 7*m + 114)/31); const day = ((h + l - 7*m + 114) % 31) + 1; return new Date(Date.UTC(year, month-1, day)); } function nthWeekday(year, month, weekday, n){ // month 0-indexed, weekday 0=Sun if(n === -1){ const last = new Date(Date.UTC(year, month+1, 0)); let d = last.getUTCDate(); while(new Date(Date.UTC(year, month, d)).getUTCDay() !== weekday) d--; return new Date(Date.UTC(year, month, d)); } const first = new Date(Date.UTC(year, month, 1)); const offset = (weekday - first.getUTCDay() + 7) % 7; return new Date(Date.UTC(year, month, 1 + offset + (n-1)*7)); } function ukSubstitute(date){ const day = date.getUTCDay(); if(day === 6){ const d = new Date(date); d.setUTCDate(d.getUTCDate()+2); return d; } if(day === 0){ const d = new Date(date); d.setUTCDate(d.getUTCDate()+1); return d; } return date; } function ukHolidays(year){ const easter = computeEaster(year); const goodFriday = new Date(easter); goodFriday.setUTCDate(easter.getUTCDate()-2); const easterMonday = new Date(easter); easterMonday.setUTCDate(easter.getUTCDate()+1); const newYear = new Date(Date.UTC(year,0,1)); const christmas = new Date(Date.UTC(year,11,25)); const boxing = new Date(Date.UTC(year,11,26)); const raw = [ ['New Year\'s Day', newYear], ['Good Friday', goodFriday], ['Easter Monday', easterMonday], ['Early May Bank Holiday', nthWeekday(year,4,1,1)], ['Spring Bank Holiday', nthWeekday(year,4,1,-1)], ['Summer Bank Holiday', nthWeekday(year,7,1,-1)], ['Christmas Day', christmas], ['Boxing Day', boxing], ]; return raw.map(([name,date]) => { const sub = (name.includes('Good Friday') || name.includes('Easter Monday') || name.includes('Bank Holiday')) ? date : ukSubstitute(date); return {name, date, observed: sub}; }); } const now = new Date(); for(let y = now.getFullYear()-1; y <= now.getFullYear()+3; y++){ const opt = document.createElement('option'); opt.value = y; opt.textContent = y; if(y === now.getFullYear()) opt.selected = true; document.getElementById('hlYear').appendChild(opt); } const yearSelect = document.getElementById('hlYear'); const table = document.getElementById('hlTable'); function fmt(d){ return d.toLocaleDateString('en-US',{weekday:'short', month:'long', day:'numeric'}); } function render(){ const year = parseInt(yearSelect.value,10); const rows = ukHolidays(year); table.innerHTML = rows.map(r => { let obsHtml = ''; if(r.observed && r.observed.getTime() !== r.date.getTime()){ obsHtml = ` (observed ${fmt(r.observed)})`; } return `
${r.name}${fmt(r.date)}${obsHtml}
`; }).join(''); } yearSelect.addEventListener('change', render); render();