@alanszp/business-days-date-fns 4.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +93 -0
- package/.gitignore +3 -0
- package/.npmignore +3 -0
- package/LICENSE +21 -0
- package/README.MD +51 -0
- package/babel.config.js +7 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.js +17 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/addBusinessDays.d.ts +1 -0
- package/dist/utils/addBusinessDays.js +42 -0
- package/dist/utils/addBusinessDays.js.map +1 -0
- package/dist/utils/addBusinessDays.test.d.ts +1 -0
- package/dist/utils/addBusinessDays.test.js +94 -0
- package/dist/utils/addBusinessDays.test.js.map +1 -0
- package/dist/utils/differenceInBusinessDay.test.d.ts +1 -0
- package/dist/utils/differenceInBusinessDay.test.js +96 -0
- package/dist/utils/differenceInBusinessDay.test.js.map +1 -0
- package/dist/utils/differenceInBusinessDays.d.ts +1 -0
- package/dist/utils/differenceInBusinessDays.js +34 -0
- package/dist/utils/differenceInBusinessDays.js.map +1 -0
- package/dist/utils/isBusinessDay.d.ts +1 -0
- package/dist/utils/isBusinessDay.js +16 -0
- package/dist/utils/isBusinessDay.js.map +1 -0
- package/dist/utils/isBusinessDay.test.d.ts +1 -0
- package/dist/utils/isBusinessDay.test.js +34 -0
- package/dist/utils/isBusinessDay.test.js.map +1 -0
- package/dist/utils/isNonBusinessDay.d.ts +1 -0
- package/dist/utils/isNonBusinessDay.js +17 -0
- package/dist/utils/isNonBusinessDay.js.map +1 -0
- package/dist/utils/isNonBusinessDay.test.d.ts +1 -0
- package/dist/utils/isNonBusinessDay.test.js +52 -0
- package/dist/utils/isNonBusinessDay.test.js.map +1 -0
- package/dist/utils/requiredArgs.d.ts +1 -0
- package/dist/utils/requiredArgs.js +10 -0
- package/dist/utils/requiredArgs.js.map +1 -0
- package/dist/utils/subBusinessDays.d.ts +1 -0
- package/dist/utils/subBusinessDays.js +14 -0
- package/dist/utils/subBusinessDays.js.map +1 -0
- package/dist/utils/subBusinessDays.test.d.ts +1 -0
- package/dist/utils/subBusinessDays.test.js +69 -0
- package/dist/utils/subBusinessDays.test.js.map +1 -0
- package/dist/utils/withNonBusinessDays.d.ts +11 -0
- package/dist/utils/withNonBusinessDays.js +45 -0
- package/dist/utils/withNonBusinessDays.js.map +1 -0
- package/dist/utils/withNonBusinessDays.test.d.ts +1 -0
- package/dist/utils/withNonBusinessDays.test.js +73 -0
- package/dist/utils/withNonBusinessDays.test.js.map +1 -0
- package/dist/utils/wrapperNonBusinessDays.d.ts +3 -0
- package/dist/utils/wrapperNonBusinessDays.js +70 -0
- package/dist/utils/wrapperNonBusinessDays.js.map +1 -0
- package/header.png +0 -0
- package/jest.config.js +10 -0
- package/package.json +39 -0
- package/src/cache/index.ts +13 -0
- package/src/index.ts +1 -0
- package/src/utils/addBusinessDays.test.ts +131 -0
- package/src/utils/addBusinessDays.ts +46 -0
- package/src/utils/differenceInBusinessDay.test.ts +176 -0
- package/src/utils/differenceInBusinessDays.ts +37 -0
- package/src/utils/isBusinessDay.test.ts +47 -0
- package/src/utils/isBusinessDay.ts +18 -0
- package/src/utils/isNonBusinessDay.test.ts +69 -0
- package/src/utils/isNonBusinessDay.ts +17 -0
- package/src/utils/requiredArgs.ts +5 -0
- package/src/utils/subBusinessDays.test.ts +99 -0
- package/src/utils/subBusinessDays.ts +10 -0
- package/src/utils/withNonBusinessDays.test.ts +82 -0
- package/src/utils/withNonBusinessDays.ts +87 -0
- package/src/utils/wrapperNonBusinessDays.ts +78 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
import { withNonBusinessDays } from "./withNonBusinessDays";
|
|
3
|
+
|
|
4
|
+
const mockNBD = [new Date("2022-01-19"), new Date("2022-01-20")];
|
|
5
|
+
const mockSerializer = jest.fn();
|
|
6
|
+
|
|
7
|
+
describe("withNonBusinessDays", () => {
|
|
8
|
+
it("bootstraping sync should return fns", () => {
|
|
9
|
+
const {
|
|
10
|
+
addBusinessDays,
|
|
11
|
+
subBusinessDays,
|
|
12
|
+
isBusinessDay,
|
|
13
|
+
isNonBusinessDay,
|
|
14
|
+
differenceInBusinessDays,
|
|
15
|
+
} = withNonBusinessDays([new Date("2022-01-01"), new Date("2022-01-10")]);
|
|
16
|
+
|
|
17
|
+
expect(typeof addBusinessDays).toBe("function");
|
|
18
|
+
expect(typeof subBusinessDays).toBe("function");
|
|
19
|
+
expect(typeof isBusinessDay).toBe("function");
|
|
20
|
+
expect(typeof isNonBusinessDay).toBe("function");
|
|
21
|
+
expect(typeof differenceInBusinessDays).toBe("function");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("bootstraping async should return fns and call serializer", async () => {
|
|
25
|
+
const mockFetchStrategy = jest.fn();
|
|
26
|
+
mockFetchStrategy.mockImplementation(() => Promise.resolve(mockNBD));
|
|
27
|
+
|
|
28
|
+
const {
|
|
29
|
+
addBusinessDays,
|
|
30
|
+
subBusinessDays,
|
|
31
|
+
isBusinessDay,
|
|
32
|
+
isNonBusinessDay,
|
|
33
|
+
differenceInBusinessDays,
|
|
34
|
+
} = withNonBusinessDays(mockFetchStrategy, {
|
|
35
|
+
serializeOptions: mockSerializer,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(typeof addBusinessDays).toBe("function");
|
|
39
|
+
expect(typeof subBusinessDays).toBe("function");
|
|
40
|
+
expect(typeof isBusinessDay).toBe("function");
|
|
41
|
+
expect(typeof isNonBusinessDay).toBe("function");
|
|
42
|
+
expect(typeof differenceInBusinessDays).toBe("function");
|
|
43
|
+
|
|
44
|
+
await addBusinessDays(new Date(), 1, { month: 1 });
|
|
45
|
+
|
|
46
|
+
expect(mockSerializer).toHaveBeenCalledWith({ month: 1 });
|
|
47
|
+
expect(mockFetchStrategy).toHaveBeenCalled();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("bootstraping async addBusinessDays", async () => {
|
|
51
|
+
const mockFetchStrategy = jest.fn();
|
|
52
|
+
mockFetchStrategy.mockImplementation(() => Promise.resolve(mockNBD));
|
|
53
|
+
const { addBusinessDays } = withNonBusinessDays(mockFetchStrategy, {
|
|
54
|
+
serializeOptions: (obj) => JSON.stringify(obj),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const result = await addBusinessDays(new Date("2022-01-18"), 1);
|
|
58
|
+
expect(result).toEqual(new Date("2022-01-21"));
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("bootstraping async throw error", async () => {
|
|
62
|
+
const mockFetchStrategy = jest.fn();
|
|
63
|
+
mockFetchStrategy.mockImplementation(() => Promise.reject());
|
|
64
|
+
try {
|
|
65
|
+
assert.throws(withNonBusinessDays.bind(mockFetchStrategy), TypeError);
|
|
66
|
+
} catch {}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("bootstraping sync addBusinessDays", () => {
|
|
70
|
+
const { addBusinessDays } = withNonBusinessDays(mockNBD);
|
|
71
|
+
|
|
72
|
+
const result = addBusinessDays(new Date("2022-01-18"), 1);
|
|
73
|
+
expect(result).toEqual(new Date("2022-01-21"));
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("bootstraping should throw error for bad input", () => {
|
|
77
|
+
try {
|
|
78
|
+
assert.throws(withNonBusinessDays.bind(null), TypeError);
|
|
79
|
+
assert.throws(withNonBusinessDays.bind(null), TypeError);
|
|
80
|
+
} catch {}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import isFunction, { isArray } from "lodash/";
|
|
2
|
+
import { Options as CacheOptions } from "lru-cache";
|
|
3
|
+
import { addBusinessDays } from "./addBusinessDays";
|
|
4
|
+
import { subBusinessDays } from "./subBusinessDays";
|
|
5
|
+
import { differenceInBusinessDays } from "./differenceInBusinessDays";
|
|
6
|
+
import {
|
|
7
|
+
wrapperDateAndNumberNonBusinessDays,
|
|
8
|
+
wrapperDateNonBusinessDays,
|
|
9
|
+
} from "./wrapperNonBusinessDays";
|
|
10
|
+
import { isNonBusinessDay } from "./isNonBusinessDay";
|
|
11
|
+
import { isBusinessDay } from "./isBusinessDay";
|
|
12
|
+
import { buildNonBusinessDaysCache } from "../cache";
|
|
13
|
+
|
|
14
|
+
export type WithNonBusinessDaysOutput<IdentifyObject> = {
|
|
15
|
+
addBusinessDays: (
|
|
16
|
+
dirtyDate: Date | number,
|
|
17
|
+
dirtyAmount: number,
|
|
18
|
+
identify?: IdentifyObject
|
|
19
|
+
) => Promise<Date> | Date;
|
|
20
|
+
subBusinessDays: (
|
|
21
|
+
dirtyDate: Date | number,
|
|
22
|
+
dirtyAmount: number,
|
|
23
|
+
identify?: IdentifyObject
|
|
24
|
+
) => Promise<Date> | Date;
|
|
25
|
+
differenceInBusinessDays: (
|
|
26
|
+
dirtyDate: Date | number,
|
|
27
|
+
dirtyAmount: number,
|
|
28
|
+
identify: IdentifyObject
|
|
29
|
+
) => Promise<number> | number;
|
|
30
|
+
isNonBusinessDay: (
|
|
31
|
+
date: Date,
|
|
32
|
+
identify: IdentifyObject
|
|
33
|
+
) => Promise<boolean> | boolean;
|
|
34
|
+
isBusinessDay: (
|
|
35
|
+
date: Date,
|
|
36
|
+
identify: IdentifyObject
|
|
37
|
+
) => Promise<boolean> | boolean;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export function withNonBusinessDays<Options>(
|
|
41
|
+
fetchStrategy: ((opts?: Options) => Promise<Date[]>) | Date[],
|
|
42
|
+
cacheOpts?: CacheOptions<string, Date[]> & {
|
|
43
|
+
serializeOptions?: (opts?: Options) => string;
|
|
44
|
+
}
|
|
45
|
+
): WithNonBusinessDaysOutput<Options> {
|
|
46
|
+
if (!isFunction(fetchStrategy) && !isArray(fetchStrategy)) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
"You must send a function for fetchStrategy or a list of dates"
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const cache = buildNonBusinessDaysCache(cacheOpts);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
addBusinessDays: wrapperDateAndNumberNonBusinessDays(
|
|
56
|
+
cache,
|
|
57
|
+
fetchStrategy,
|
|
58
|
+
addBusinessDays,
|
|
59
|
+
cacheOpts?.serializeOptions
|
|
60
|
+
),
|
|
61
|
+
differenceInBusinessDays: wrapperDateAndNumberNonBusinessDays(
|
|
62
|
+
cache,
|
|
63
|
+
|
|
64
|
+
fetchStrategy,
|
|
65
|
+
differenceInBusinessDays,
|
|
66
|
+
cacheOpts?.serializeOptions
|
|
67
|
+
),
|
|
68
|
+
subBusinessDays: wrapperDateAndNumberNonBusinessDays(
|
|
69
|
+
cache,
|
|
70
|
+
fetchStrategy,
|
|
71
|
+
subBusinessDays,
|
|
72
|
+
cacheOpts?.serializeOptions
|
|
73
|
+
),
|
|
74
|
+
isNonBusinessDay: wrapperDateNonBusinessDays(
|
|
75
|
+
cache,
|
|
76
|
+
fetchStrategy,
|
|
77
|
+
isNonBusinessDay,
|
|
78
|
+
cacheOpts?.serializeOptions
|
|
79
|
+
),
|
|
80
|
+
isBusinessDay: wrapperDateNonBusinessDays(
|
|
81
|
+
cache,
|
|
82
|
+
fetchStrategy,
|
|
83
|
+
isBusinessDay,
|
|
84
|
+
cacheOpts?.serializeOptions
|
|
85
|
+
),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { InternalServerError } from "@alanszp/errors";
|
|
2
|
+
import isArray from "lodash/isArray";
|
|
3
|
+
import LRUCache from "lru-cache";
|
|
4
|
+
|
|
5
|
+
export function wrapperDateAndNumberNonBusinessDays<IdentifyObject, R>(
|
|
6
|
+
cacheNBD: LRUCache<string, Date[]>,
|
|
7
|
+
fetchStrategy: ((opts?: IdentifyObject) => Promise<Date[]>) | Date[],
|
|
8
|
+
fn: (
|
|
9
|
+
nonBusinessDays: Date[],
|
|
10
|
+
dirtyDate: Date | number,
|
|
11
|
+
dirtyAmount: number
|
|
12
|
+
) => R,
|
|
13
|
+
serializeOptions?: (opts?: IdentifyObject) => string
|
|
14
|
+
) {
|
|
15
|
+
if (isArray(fetchStrategy)) {
|
|
16
|
+
return (dirtyDate: Date | number, dirtyAmount: number) =>
|
|
17
|
+
fn(fetchStrategy, dirtyDate, dirtyAmount);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return async (
|
|
21
|
+
dirtyDate: Date | number,
|
|
22
|
+
dirtyAmount: number,
|
|
23
|
+
identify?: IdentifyObject
|
|
24
|
+
): Promise<R> => {
|
|
25
|
+
const cacheIdentify = serializeOptions
|
|
26
|
+
? serializeOptions(identify)
|
|
27
|
+
: JSON.stringify(identify);
|
|
28
|
+
const cache = cacheNBD.get(cacheIdentify);
|
|
29
|
+
|
|
30
|
+
let nonBusinessDays: Date[] = [];
|
|
31
|
+
|
|
32
|
+
if (!cache) {
|
|
33
|
+
try {
|
|
34
|
+
nonBusinessDays = await fetchStrategy(identify);
|
|
35
|
+
cacheNBD.set(cacheIdentify, nonBusinessDays);
|
|
36
|
+
} catch (error: unknown) {
|
|
37
|
+
throw new InternalServerError(error);
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
nonBusinessDays = cache;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return fn(nonBusinessDays, dirtyDate, dirtyAmount);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function wrapperDateNonBusinessDays<IdentifyObject, R>(
|
|
48
|
+
cacheNBD: LRUCache<string, Date[]>,
|
|
49
|
+
fetchStrategy: ((opts?: IdentifyObject) => Promise<Date[]>) | Date[],
|
|
50
|
+
fn: (nonBusinessDays: Date[], date: Date) => R,
|
|
51
|
+
serializeOptions?: (opts?: IdentifyObject) => string
|
|
52
|
+
) {
|
|
53
|
+
if (isArray(fetchStrategy)) {
|
|
54
|
+
return (date: Date) => fn(fetchStrategy, date);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return async (date: Date, identify?: IdentifyObject): Promise<R> => {
|
|
58
|
+
const cacheIdentify = serializeOptions
|
|
59
|
+
? serializeOptions(identify)
|
|
60
|
+
: JSON.stringify(identify);
|
|
61
|
+
const cache = cacheNBD.get(cacheIdentify);
|
|
62
|
+
|
|
63
|
+
let nonBusinessDays: Date[] = [];
|
|
64
|
+
|
|
65
|
+
if (!cache) {
|
|
66
|
+
try {
|
|
67
|
+
nonBusinessDays = await fetchStrategy(identify);
|
|
68
|
+
cacheNBD.set(cacheIdentify, nonBusinessDays);
|
|
69
|
+
} catch (error: unknown) {
|
|
70
|
+
throw new InternalServerError(error);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
nonBusinessDays = cache;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return fn(nonBusinessDays, date);
|
|
77
|
+
};
|
|
78
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"rootDir": "src",
|
|
4
|
+
"outDir": "dist",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"target": "es6",
|
|
7
|
+
"types": ["jest", "node"],
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
|
|
11
|
+
"alwaysStrict": true,
|
|
12
|
+
"strictNullChecks": true
|
|
13
|
+
},
|
|
14
|
+
"exclude": ["node_modules"]
|
|
15
|
+
}
|