Skip to content

Commit 581ebd2

Browse files
committed
fix: bank holidays fix
1 parent 0b6a4f4 commit 581ebd2

4 files changed

Lines changed: 165 additions & 11 deletions

File tree

src/components/Holidays/RequestLeave.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { format } from 'date-fns'
1010
import { CalendarIcon } from 'lucide-react'
1111
import { useRouter } from 'next/navigation'
1212
import { Toaster, toast } from 'sonner'
13-
import { getTotalDaysBetween, isDayOff, getIsMultipleDays } from '@/lib/utils/DaysUtil'
13+
import { getTotalDaysBetween, getIsMultipleDays } from '@/lib/utils/DaysUtil'
1414

1515
interface RequestLeaveProps {
1616
remainingDays: number

src/utils/BankHolidays.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
export const bankHolidays = [
2-
{ date: new Date(2025, 3, 18), name: 'Good Friday' },
3-
{ date: new Date(2025, 3, 21), name: 'Easter Monday' },
4-
{ date: new Date(2025, 4, 5), name: 'Early May bank holiday' },
5-
{ date: new Date(2025, 5, 26), name: 'Spring bank holiday' },
6-
{ date: new Date(2025, 7, 25), name: 'Summer bank holiday' },
7-
{ date: new Date(2025, 11, 25), name: 'Christmas Day' },
8-
{ date: new Date(2025, 11, 26), name: 'Boxing Day' },
2+
// 2025 Bank Holidays
3+
new Date(2025, 0, 1), // New Year's Day
4+
new Date(2025, 3, 18), // Good Friday
5+
new Date(2025, 3, 21), // Easter Monday
6+
new Date(2025, 4, 5), // Early May bank holiday
7+
new Date(2025, 4, 26), // Spring bank holiday
8+
new Date(2025, 7, 25), // Summer bank holiday
9+
new Date(2025, 11, 25), // Christmas Day
10+
new Date(2025, 11, 26), // Boxing Day
11+
12+
// 2026 Bank Holidays
13+
new Date(2026, 0, 1), // New Year's Day
14+
new Date(2026, 3, 3), // Good Friday
15+
new Date(2026, 3, 6), // Easter Monday
16+
new Date(2026, 4, 4), // Early May bank holiday
17+
new Date(2026, 4, 25), // Spring bank holiday
18+
new Date(2026, 7, 31), // Summer bank holiday
19+
new Date(2026, 11, 25), // Christmas Day
20+
new Date(2026, 11, 28), // Boxing Day
921
]

src/utils/DaysUtil.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { bankHolidays } from './BankHolidays'
33
export const isDayOff = (date: Date) => {
44
const isSunday = date.getDay() === 0
55
const isSaturday = date.getDay() === 6
6-
const isBankHoliday = bankHolidays.some((h) => h.date.toISOString() === date.toISOString())
6+
const isBankHoliday = bankHolidays.some((h) => h.toISOString() === date.toISOString())
77

88
return isSunday || isSaturday || isBankHoliday
99
}

tests/DaysUtil.test.ts

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,48 @@ describe('DaysUtil', () => {
1212
})
1313

1414
test('returns true for bank holidays', () => {
15-
bankHolidays.forEach(({ date }) => {
15+
bankHolidays.forEach((date) => {
1616
expect(isDayOff(date)).toBe(true)
1717
})
1818
})
1919

2020
test("returns false for a regular weekday that's not a bank holiday", () => {
2121
expect(isDayOff(new Date(2025, 3, 22))).toBe(false) // Tuesday, 22 April 2025 (Not a holiday)
22-
expect(isDayOff(new Date(2025, 3, 25))).toBe(false) // Friday, 23 April 2025 (Not a holiday)
22+
expect(isDayOff(new Date(2025, 3, 25))).toBe(false) // Friday, 25 April 2025 (Not a holiday)
23+
})
24+
25+
// New comprehensive tests for specific bank holidays
26+
test('correctly identifies specific 2025 bank holidays', () => {
27+
expect(isDayOff(new Date(2025, 0, 1))).toBe(true) // New Year's Day - Jan 1
28+
expect(isDayOff(new Date(2025, 3, 18))).toBe(true) // Good Friday - April 18
29+
expect(isDayOff(new Date(2025, 3, 21))).toBe(true) // Easter Monday - April 21
30+
expect(isDayOff(new Date(2025, 4, 5))).toBe(true) // Early May bank holiday - May 5
31+
expect(isDayOff(new Date(2025, 4, 26))).toBe(true) // Spring bank holiday - May 26
32+
expect(isDayOff(new Date(2025, 7, 25))).toBe(true) // Summer bank holiday - Aug 25
33+
expect(isDayOff(new Date(2025, 11, 25))).toBe(true) // Christmas Day - Dec 25
34+
expect(isDayOff(new Date(2025, 11, 26))).toBe(true) // Boxing Day - Dec 26
35+
})
36+
37+
test('correctly identifies specific 2026 bank holidays', () => {
38+
expect(isDayOff(new Date(2026, 0, 1))).toBe(true) // New Year's Day - Jan 1
39+
expect(isDayOff(new Date(2026, 3, 3))).toBe(true) // Good Friday - April 3
40+
expect(isDayOff(new Date(2026, 3, 6))).toBe(true) // Easter Monday - April 6
41+
expect(isDayOff(new Date(2026, 4, 4))).toBe(true) // Early May bank holiday - May 4
42+
expect(isDayOff(new Date(2026, 4, 25))).toBe(true) // Spring bank holiday - May 25
43+
expect(isDayOff(new Date(2026, 7, 31))).toBe(true) // Summer bank holiday - Aug 31
44+
expect(isDayOff(new Date(2026, 11, 25))).toBe(true) // Christmas Day - Dec 25
45+
expect(isDayOff(new Date(2026, 11, 28))).toBe(true) // Boxing Day - Dec 28
46+
})
47+
48+
test('correctly rejects dates that are NOT bank holidays', () => {
49+
expect(isDayOff(new Date(2025, 0, 2))).toBe(false) // Jan 2 (not a holiday)
50+
expect(isDayOff(new Date(2025, 3, 17))).toBe(false) // April 17 (day before Good Friday)
51+
expect(isDayOff(new Date(2025, 3, 19))).toBe(true) // April 19 is Saturday (weekend)
52+
expect(isDayOff(new Date(2025, 3, 22))).toBe(false) // April 22 (day after Easter Monday)
53+
expect(isDayOff(new Date(2025, 4, 4))).toBe(true) // May 4 is Sunday (weekend)
54+
expect(isDayOff(new Date(2025, 4, 6))).toBe(false) // May 6 (day after Early May holiday)
55+
expect(isDayOff(new Date(2025, 11, 24))).toBe(false) // Dec 24 (Christmas Eve, not a UK bank holiday)
56+
expect(isDayOff(new Date(2025, 11, 29))).toBe(false) // Dec 29 (Monday after Boxing Day, not a holiday)
2357
})
2458
})
2559

@@ -39,6 +73,87 @@ describe('DaysUtil', () => {
3973
expect(getTotalDaysBetween(new Date(2025, 3, 17), new Date(2025, 3, 24))).toBe(4) // easter weekend
4074
expect(getTotalDaysBetween(new Date(2025, 2, 3), new Date(2025, 2, 14))).toBe(10)
4175
})
76+
77+
// New comprehensive tests for edge cases
78+
test('handles periods around New Year correctly', () => {
79+
// Dec 30 2024 (Mon) to Jan 3 2025 (Fri) - should exclude Jan 1 (New Year's Day)
80+
expect(getTotalDaysBetween(new Date(2024, 11, 30), new Date(2025, 0, 3))).toBe(4)
81+
82+
// Dec 31 2024 (Tue) to Jan 2 2025 (Thu) - should exclude Jan 1 (New Year's Day)
83+
expect(getTotalDaysBetween(new Date(2024, 11, 31), new Date(2025, 0, 2))).toBe(2)
84+
})
85+
86+
test('handles Easter period correctly', () => {
87+
// April 17-22 (Thu-Tue) includes Good Friday (18th) and Easter Monday (21st), plus weekend
88+
// Working days: 17th (Thu), 22nd (Tue) = 2 days
89+
expect(getTotalDaysBetween(new Date(2025, 3, 17), new Date(2025, 3, 22))).toBe(2)
90+
91+
// April 14-25 (Mon-Fri) - longer period including Easter
92+
// Excludes: 18th (Good Friday), 19th-20th (weekend), 21st (Easter Monday)
93+
// Working days: 14th, 15th, 16th, 17th, 22nd, 23rd, 24th, 25th = 8 days
94+
expect(getTotalDaysBetween(new Date(2025, 3, 14), new Date(2025, 3, 25))).toBe(8)
95+
})
96+
97+
test('handles May bank holidays correctly', () => {
98+
// May 1-9 (Thu-Fri) includes Early May holiday (5th) and weekend
99+
// Working days: 1st, 2nd, 6th, 7th, 8th, 9th = 6 days
100+
expect(getTotalDaysBetween(new Date(2025, 4, 1), new Date(2025, 4, 9))).toBe(6)
101+
102+
// May 22-30 (Thu-Fri) includes Spring bank holiday (26th) and weekend
103+
// Working days: 22nd, 23rd, 27th, 28th, 29th, 30th = 6 days
104+
expect(getTotalDaysBetween(new Date(2025, 4, 22), new Date(2025, 4, 30))).toBe(6)
105+
})
106+
107+
test('handles Christmas period correctly', () => {
108+
// Dec 22-30 (Mon-Tue) includes Christmas Day (25th), Boxing Day (26th), and weekend
109+
// Working days: 22nd, 23rd, 24th, 29th, 30th = 5 days
110+
expect(getTotalDaysBetween(new Date(2025, 11, 22), new Date(2025, 11, 30))).toBe(5)
111+
})
112+
113+
test('handles 2026 Easter period correctly', () => {
114+
// April 1-8 (Wed-Wed) includes Good Friday (3rd), Easter Monday (6th), and weekend
115+
// Working days: 1st (Wed), 2nd (Thu), 7th (Tue), 8th (Wed) = 4 days
116+
expect(getTotalDaysBetween(new Date(2026, 3, 1), new Date(2026, 3, 8))).toBe(4)
117+
})
118+
119+
test('handles 2026 Christmas period correctly', () => {
120+
// Dec 23-30 (Wed-Wed) includes Christmas Day (25th), Boxing Day (28th), and weekend
121+
// Working days: 23rd (Wed), 24th (Thu), 29th (Tue), 30th (Wed) = 4 days
122+
expect(getTotalDaysBetween(new Date(2026, 11, 23), new Date(2026, 11, 30))).toBe(4)
123+
})
124+
125+
test('handles full month calculations correctly', () => {
126+
// January 2025: 31 days total, minus weekends (8 days) and New Year's Day = 22 working days
127+
expect(getTotalDaysBetween(new Date(2025, 0, 1), new Date(2025, 0, 31))).toBe(22)
128+
129+
// April 2025: 30 days total, minus weekends (8 days), Good Friday, and Easter Monday = 20 working days
130+
expect(getTotalDaysBetween(new Date(2025, 3, 1), new Date(2025, 3, 30))).toBe(20)
131+
})
132+
133+
test('handles single day calculations', () => {
134+
// Single working day
135+
expect(getTotalDaysBetween(new Date(2025, 0, 2), new Date(2025, 0, 2))).toBe(1)
136+
137+
// Single bank holiday
138+
expect(getTotalDaysBetween(new Date(2025, 0, 1), new Date(2025, 0, 1))).toBe(0)
139+
140+
// Single weekend day
141+
expect(getTotalDaysBetween(new Date(2025, 0, 4), new Date(2025, 0, 4))).toBe(0) // Saturday
142+
})
143+
144+
test('handles edge case with bank holidays falling on weekends', () => {
145+
// If a bank holiday falls on a weekend, it should still be counted as a day off
146+
// Test with various scenarios to ensure no double-counting
147+
148+
// Check if any 2025 bank holidays fall on weekends
149+
const newYearsDay = new Date(2025, 0, 1) // Wednesday
150+
const goodFriday = new Date(2025, 3, 18) // Friday
151+
const easterMonday = new Date(2025, 3, 21) // Monday
152+
153+
expect(newYearsDay.getDay()).toBe(3) // Wednesday
154+
expect(goodFriday.getDay()).toBe(5) // Friday
155+
expect(easterMonday.getDay()).toBe(1) // Monday
156+
})
42157
})
43158

44159
describe('isMultipleDays', () => {
@@ -57,4 +172,31 @@ describe('DaysUtil', () => {
57172
expect(getIsMultipleDays(undefined, new Date(2025, 0, 3))).toBe(false)
58173
})
59174
})
175+
176+
describe('BankHolidays integrity', () => {
177+
test('has correct number of bank holidays for 2025 and 2026', () => {
178+
expect(bankHolidays).toHaveLength(16) // 8 for 2025 + 8 for 2026
179+
})
180+
181+
test('all bank holidays are in 2025 or 2026', () => {
182+
bankHolidays.forEach((date) => {
183+
const year = date.getFullYear()
184+
expect(year === 2025 || year === 2026).toBe(true)
185+
})
186+
})
187+
188+
test('bank holidays are in chronological order', () => {
189+
for (let i = 1; i < bankHolidays.length; i++) {
190+
expect(bankHolidays[i].getTime()).toBeGreaterThan(bankHolidays[i - 1].getTime())
191+
}
192+
})
193+
194+
test('has correct number of holidays per year', () => {
195+
const holidays2025 = bankHolidays.filter((date) => date.getFullYear() === 2025)
196+
const holidays2026 = bankHolidays.filter((date) => date.getFullYear() === 2026)
197+
198+
expect(holidays2025).toHaveLength(8)
199+
expect(holidays2026).toHaveLength(8)
200+
})
201+
})
60202
})

0 commit comments

Comments
 (0)