Skip to content

Commit 5be867b

Browse files
authored
feat(maths): add IsLeapYear (#40)
1 parent ec66370 commit 5be867b

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

Maths/IsLeapYear.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* @function IsLeapYear
3+
* @description Checks if a year is a leap year (Gregorian calendar).
4+
* A year is a leap year if it is divisible by 4 but not by 400 or if it is divisible by 400.
5+
* @param {number} year - A year, natural number > 0.
6+
* @return {boolean} - True if given year is a leap year.
7+
* @see https://en.wikipedia.org/wiki/Leap_year#Gregorian_calendar
8+
* @example IsLeapYear(2000) = true
9+
* @example IsLeapYear(2001) = false
10+
*/
11+
12+
export const IsLeapYear = (year: number): boolean => {
13+
if (year <= 0 || !Number.isInteger(year)) {
14+
throw new Error("year must be a natural number > 0");
15+
}
16+
17+
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
18+
};

Maths/test/IsLeapYear.test.ts

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { IsLeapYear } from "../IsLeapYear";
2+
3+
describe("IsLeapYear", () => {
4+
test.each([4, 8, 12, 2004])(
5+
"a year is a leap year it is divisible by 4 but not by 400 like %i",
6+
(year) => {
7+
expect(year % 4 === 0).toBe(true);
8+
expect(year % 400 === 0).toBe(false);
9+
expect(IsLeapYear(year)).toBe(true);
10+
},
11+
);
12+
13+
test.each([400, 800, 1200, 1600, 2000, 2400, 40000])(
14+
"a year is a leap year it is divisible by 400 like %i",
15+
(year) => {
16+
expect(year % 400 === 0).toBe(true);
17+
expect(IsLeapYear(year)).toBe(true);
18+
},
19+
);
20+
21+
test.each([1, 313, 1997, 2001, 2021, 13337])(
22+
"a year is not a leap year if it is not divisible by 4 like %i",
23+
(year) => {
24+
expect(year % 4 === 0).toBe(false);
25+
expect(IsLeapYear(year)).toBe(false);
26+
},
27+
);
28+
29+
test.each([100, 200, 300, 700, 2100])(
30+
"a year is not a leap year if it is divisible by 100 but not by 400 like %i",
31+
(year) => {
32+
expect(year % 100 === 0).toBe(true);
33+
expect(year % 400 === 0).toBe(false);
34+
expect(IsLeapYear(year)).toBe(false);
35+
},
36+
);
37+
38+
test.each([1, 2022, 3000000])(
39+
"a year is supported if it is a natural number > 0 like %i",
40+
(year) => {
41+
expect(year > 0).toBe(true);
42+
expect(Number.isInteger(year)).toBe(true);
43+
expect(() => IsLeapYear(year)).not.toThrow();
44+
},
45+
);
46+
47+
test.each([-1, -10, -Infinity])(
48+
"a year is not supported if it is negative like %i",
49+
(year) => {
50+
expect(year < 0).toBe(true);
51+
expect(() => IsLeapYear(year)).toThrow("year must be a natural number > 0");
52+
},
53+
);
54+
55+
test.each([0.1, 1.2, 4.2])(
56+
"a year is not supported if it is not an integer %d",
57+
(year) => {
58+
expect(Number.isInteger(year)).toBe(false);
59+
expect(() => IsLeapYear(year)).toThrow("year must be a natural number > 0");
60+
},
61+
);
62+
63+
test("a year is not supported if it is 0", () => {
64+
expect(() => IsLeapYear(0)).toThrow("year must be a natural number > 0");
65+
})
66+
});

0 commit comments

Comments
 (0)