Skip to content

Commit aae287e

Browse files
authored
Add more date utility functions (#33)
1 parent bb3fb12 commit aae287e

File tree

3 files changed

+118
-4
lines changed

3 files changed

+118
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
- added `dateIsFirstDayOfMonth`, `dateIsLeapYear`, `dateIsWeekend` and `getNextBusinessDate` utility functions
11+
1012
## [0.5.0] - 2024-03-15
1113

1214
### Added

src/lib/date.spec.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { dateIsValid, dateIsLastDayOfMonth, dateDifferenceInDays } from "./date";
1+
import {
2+
dateIsValid,
3+
dateIsFirstDayOfMonth,
4+
dateIsLastDayOfMonth,
5+
dateIsLeapYear,
6+
dateIsWeekend,
7+
dateDifferenceInDays,
8+
getNextBusinessDate,
9+
} from "./date";
210

311
describe("date tests", () => {
412
test.each([
@@ -22,6 +30,14 @@ describe("date tests", () => {
2230
expect(dateIsValid(date)).toBe(expected);
2331
});
2432

33+
test.each([
34+
[new Date(2015, 0, 1), true],
35+
[new Date(2015, 1, 1), true],
36+
[new Date(2015, 12, 30), false],
37+
])("dateIsFirstDayOfMonth", (date, expected) => {
38+
expect(dateIsFirstDayOfMonth(date)).toBe(expected);
39+
});
40+
2541
test.each([
2642
[new Date(2014, 12, 31), true],
2743
[new Date(2014, 12, 30), false],
@@ -30,6 +46,34 @@ describe("date tests", () => {
3046
expect(dateIsLastDayOfMonth(date)).toBe(expected);
3147
});
3248

49+
test.each([
50+
[new Date(2000, 0, 1), true],
51+
[new Date(2004, 0, 1), true],
52+
[new Date(2008, 0, 1), true],
53+
[new Date(2009, 0, 1), false],
54+
[new Date(2010, 0, 1), false],
55+
[new Date(1900, 0, 1), false],
56+
[new Date(2100, 0, 1), false],
57+
[new Date(2200, 0, 1), false],
58+
[new Date(2300, 0, 1), false],
59+
[new Date(2400, 0, 1), true],
60+
])("dateIsLeapYear", (date, expected) => {
61+
expect(dateIsLeapYear(date)).toBe(expected);
62+
});
63+
64+
test.each([
65+
[new Date(2024, 0, 1), false], // Monday
66+
[new Date(2024, 0, 2), false], // Tuesday
67+
[new Date(2024, 0, 3), false], // Wednesday
68+
[new Date(2024, 0, 4), false], // Thursday
69+
[new Date(2024, 0, 5), false], // Friday
70+
[new Date(2024, 0, 6), true], // Saturday
71+
[new Date(2024, 0, 7), true], // Sunday
72+
[new Date(2024, 0, 8), false], // Monday
73+
])("dateIsWeekend", (date, expected) => {
74+
expect(dateIsWeekend(date)).toBe(expected);
75+
});
76+
3377
test.each([
3478
[new Date(2014, 3, 15), new Date(2014, 3, 15), 0],
3579
[new Date(2014, 3, 15), new Date(2014, 3, 16), 1],
@@ -38,7 +82,30 @@ describe("date tests", () => {
3882
[new Date(2014, 3, 15, 23, 59), new Date(2014, 3, 16, 0, 0), 1],
3983
[null as unknown as Date, new Date(), Number.NaN],
4084
[new Date(), null as unknown as Date, Number.NaN],
85+
[undefined as unknown as Date, new Date(), Number.NaN],
86+
[new Date(), undefined as unknown as Date, Number.NaN],
87+
[42 as unknown as Date, new Date(), Number.NaN],
88+
[new Date(), 42 as unknown as Date, Number.NaN],
89+
["2014-03-15" as unknown as Date, new Date(), Number.NaN],
90+
[new Date(), "2014-03-15" as unknown as Date, Number.NaN],
4191
])("dateDifferenceInDays", (dateFrom, dateTo, expected) => {
4292
expect(dateDifferenceInDays(dateFrom, dateTo)).toBe(expected);
4393
});
94+
95+
test.each([
96+
[new Date(2024, 0, 1), new Date(2024, 0, 2)],
97+
[new Date(2024, 0, 2), new Date(2024, 0, 3)],
98+
[new Date(2024, 0, 3), new Date(2024, 0, 4)],
99+
[new Date(2024, 0, 4), new Date(2024, 0, 5)],
100+
[new Date(2024, 0, 5), new Date(2024, 0, 8)],
101+
[new Date(2024, 0, 6), new Date(2024, 0, 8)],
102+
[new Date(2024, 0, 7), new Date(2024, 0, 8)],
103+
[new Date(2024, 0, 8), new Date(2024, 0, 9)],
104+
[null as unknown as Date, new Date(Number.NaN)],
105+
[undefined as unknown as Date, new Date(Number.NaN)],
106+
[42 as unknown as Date, new Date(Number.NaN)],
107+
["test" as unknown as Date, new Date(Number.NaN)],
108+
])("getNextBusinessDate", (date, expected) => {
109+
expect(getNextBusinessDate(date).getDate()).toBe(expected.getDate());
110+
});
44111
});

src/lib/date.ts

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
1-
import { isDate, isValid, isLastDayOfMonth, differenceInCalendarDays } from "date-fns";
1+
import {
2+
isDate,
3+
isValid,
4+
isFirstDayOfMonth,
5+
isLastDayOfMonth,
6+
isLeapYear,
7+
isWeekend,
8+
differenceInCalendarDays,
9+
addBusinessDays,
10+
} from "date-fns";
211

312
/**
413
* Check whether the date is valid
@@ -9,13 +18,40 @@ export function dateIsValid(date: Date): boolean {
918
return isDate(date) && isValid(date);
1019
}
1120

21+
/**
22+
* Check whether the date is the first day of the month
23+
* @param date The date
24+
* @returns A boolean indicating whether the date is the first day of the month
25+
*/
26+
export function dateIsFirstDayOfMonth(date: Date): boolean {
27+
return dateIsValid(date) && isFirstDayOfMonth(date);
28+
}
29+
1230
/**
1331
* Check whether the date is the last day of the month
1432
* @param date The date
1533
* @returns A boolean indicating whether the date is the last day of the month
1634
*/
1735
export function dateIsLastDayOfMonth(date: Date): boolean {
18-
return isDate(date) && isLastDayOfMonth(date);
36+
return dateIsValid(date) && isLastDayOfMonth(date);
37+
}
38+
39+
/**
40+
* Check whether the date is a leap year
41+
* @param date The date
42+
* @returns A boolean indicating whether the date is a leap year
43+
*/
44+
export function dateIsLeapYear(date: Date): boolean {
45+
return dateIsValid(date) && isLeapYear(date);
46+
}
47+
48+
/**
49+
* Check whether the date is a weekend
50+
* @param date The date
51+
* @returns A boolean indicating whether the date is a weekend
52+
*/
53+
export function dateIsWeekend(date: Date): boolean {
54+
return dateIsValid(date) && isWeekend(date);
1955
}
2056

2157
/**
@@ -26,5 +62,14 @@ export function dateIsLastDayOfMonth(date: Date): boolean {
2662
* @returns The difference in days between two dates
2763
*/
2864
export function dateDifferenceInDays(from: Date, to: Date): number {
29-
return Math.abs(differenceInCalendarDays(from, to));
65+
return dateIsValid(from) && dateIsValid(to) ? Math.abs(differenceInCalendarDays(from, to)) : Number.NaN;
66+
}
67+
68+
/**
69+
* Get the next business date
70+
* @param date The date
71+
* @returns The next business date
72+
*/
73+
export function getNextBusinessDate(date: Date): Date {
74+
return dateIsValid(date) ? addBusinessDays(date, 1) : new Date(Number.NaN);
3075
}

0 commit comments

Comments
 (0)