nhb-toolbox 4.20.70 → 4.20.80
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/CHANGELOG.md +8 -0
- package/dist/cjs/date/Chronos.js +4 -3
- package/dist/cjs/date/plugins/businessPlugin.js +27 -19
- package/dist/dts/date/plugins/businessPlugin.d.ts +51 -22
- package/dist/dts/date/types.d.ts +36 -8
- package/dist/dts/utils/types.d.ts +20 -10
- package/dist/esm/date/Chronos.js +4 -3
- package/dist/esm/date/plugins/businessPlugin.js +27 -19
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,14 @@ All notable changes to the package will be documented here.
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [4.20.80] - 2025-10-07
|
|
10
|
+
|
|
11
|
+
### 🕧 Updates in Chronos
|
|
12
|
+
|
|
13
|
+
- **Added** _overload signatures_ for `isWeekend`, `isWorkDay` and `isBusinessHour` methods from `businessPlugin`.
|
|
14
|
+
- **Fixed** issues with `isBusinessHour`: previously skipped _business start and end hours_ in some cases.
|
|
15
|
+
- **Added** new _utility type_ `RangeTuple` to create _ranged tuple_.
|
|
16
|
+
|
|
9
17
|
## [4.20.69-70] - 2025-10-07
|
|
10
18
|
|
|
11
19
|
### 🕧 Updates in Chronos
|
package/dist/cjs/date/Chronos.js
CHANGED
|
@@ -204,19 +204,20 @@ class Chronos {
|
|
|
204
204
|
}
|
|
205
205
|
#normalizeDuration(result, absolute, isFuture) {
|
|
206
206
|
const entries = Object.entries(result);
|
|
207
|
+
const updated = {};
|
|
207
208
|
if (!absolute && !isFuture) {
|
|
208
209
|
for (const [key, value] of entries) {
|
|
209
210
|
if (value !== 0) {
|
|
210
|
-
|
|
211
|
+
updated[key] = value * -1;
|
|
211
212
|
}
|
|
212
213
|
}
|
|
213
214
|
}
|
|
214
215
|
else if (absolute) {
|
|
215
216
|
for (const [key, value] of entries) {
|
|
216
|
-
|
|
217
|
+
updated[key] = Math.abs(value);
|
|
217
218
|
}
|
|
218
219
|
}
|
|
219
|
-
return
|
|
220
|
+
return updated;
|
|
220
221
|
}
|
|
221
222
|
get year() {
|
|
222
223
|
return this.#date.getFullYear();
|
|
@@ -2,36 +2,44 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.businessPlugin = void 0;
|
|
4
4
|
const non_primitives_1 = require("../../guards/non-primitives");
|
|
5
|
+
const primitives_1 = require("../../guards/primitives");
|
|
5
6
|
const constants_1 = require("../constants");
|
|
6
7
|
const businessPlugin = (ChronosClass) => {
|
|
7
8
|
const internalDate = ChronosClass[constants_1.INTERNALS].internalDate;
|
|
8
|
-
ChronosClass.prototype.isWeekend = function (
|
|
9
|
+
ChronosClass.prototype.isWeekend = function (determiner = 0, weekendLength = 2) {
|
|
9
10
|
const day = internalDate(this).getDay();
|
|
10
|
-
if ((0, non_primitives_1.isValidArray)(
|
|
11
|
-
return
|
|
11
|
+
if ((0, non_primitives_1.isValidArray)(determiner)) {
|
|
12
|
+
return determiner.includes(day);
|
|
12
13
|
}
|
|
13
|
-
const lastDayOfWeek = (
|
|
14
|
+
const lastDayOfWeek = (determiner + 6) % 7;
|
|
14
15
|
const computedWeekendDays = Array.from({ length: weekendLength }, (_, i) => (lastDayOfWeek - i + 7) % 7);
|
|
15
16
|
return computedWeekendDays.includes(day);
|
|
16
17
|
};
|
|
17
|
-
ChronosClass.prototype.isWorkday = function (
|
|
18
|
-
|
|
18
|
+
ChronosClass.prototype.isWorkday = function (determiner = 0, weekendLength = 2) {
|
|
19
|
+
if ((0, non_primitives_1.isValidArray)(determiner)) {
|
|
20
|
+
return !this.isWeekend(determiner);
|
|
21
|
+
}
|
|
22
|
+
return !this.isWeekend(determiner, weekendLength);
|
|
19
23
|
};
|
|
20
24
|
ChronosClass.prototype.isBusinessHour = function (options) {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
const _isBusinessHour = () => {
|
|
26
|
+
const { businessStartHour = 9, businessEndHour = 17 } = options ?? {};
|
|
27
|
+
if (businessStartHour === businessEndHour) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const hour = internalDate(this).getHours();
|
|
31
|
+
if (businessStartHour < businessEndHour) {
|
|
32
|
+
return hour >= businessStartHour && hour < businessEndHour;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
return hour >= businessStartHour || hour < businessEndHour;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
if (options && 'weekendDays' in options && !(0, primitives_1.isUndefined)(options?.weekendDays)) {
|
|
39
|
+
return this.isWorkday(options?.weekendDays) && _isBusinessHour();
|
|
34
40
|
}
|
|
41
|
+
const { weekStartsOn = 0, weekendLength = 2 } = (options ?? {});
|
|
42
|
+
return this.isWorkday(weekStartsOn, weekendLength) && _isBusinessHour();
|
|
35
43
|
};
|
|
36
44
|
ChronosClass.prototype.toFiscalQuarter = function (startMonth = 7) {
|
|
37
45
|
const month = internalDate(this).getMonth() + 1;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import type { Enumerate, NumberRange } from '../../number/types';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { RangeTuple } from '../../utils/types';
|
|
3
|
+
import type { AcademicYear, BusinessOptionsBasic, BusinessOptionsWeekends, Quarter } from '../types';
|
|
4
4
|
type MainChronos = typeof import('../Chronos').Chronos;
|
|
5
5
|
declare module '../Chronos' {
|
|
6
6
|
interface Chronos {
|
|
7
7
|
/**
|
|
8
|
-
* @instance Checks if the current date falls on a weekend.
|
|
8
|
+
* @instance Checks if the current date falls on a weekend using week start day and weekend length.
|
|
9
9
|
*
|
|
10
10
|
* @param weekStartsOn Optional. The day index (0–6) that the week starts on. Default is `0` (Sunday).
|
|
11
11
|
* @param weekendLength Optional. The number of consecutive days at the end of the week considered as weekend. Must be between 1 and 4. Default is `2`.
|
|
12
|
-
* @param weekendDays Optional. A tuple of custom weekend day indices (0–6). Its length must match `weekendLength`. If provided, this overrides `weekStartsOn` + `weekendLength` calculation.
|
|
13
12
|
* @returns `true` if the current date is a weekend day according to the provided parameters; otherwise `false`.
|
|
14
13
|
*
|
|
15
14
|
* @description
|
|
@@ -19,7 +18,6 @@ declare module '../Chronos' {
|
|
|
19
18
|
* - By default (`weekStartsOn = 0`, `weekendLength = 2`), Saturday (6) and Friday (5) are considered weekend.
|
|
20
19
|
* - `weekStartsOn` sets the start of the week for calculating weekend days.
|
|
21
20
|
* - `weekendLength` sets how many days at the end of the week are treated as weekend.
|
|
22
|
-
* - `weekendDays`, if provided, is used directly as the weekend days instead of calculating from `weekStartsOn` + `weekendLength`.
|
|
23
21
|
*
|
|
24
22
|
* @example
|
|
25
23
|
* // Default: Saturday & Friday are weekend
|
|
@@ -30,17 +28,30 @@ declare module '../Chronos' {
|
|
|
30
28
|
*
|
|
31
29
|
* // Custom 3-day weekend (Friday, Saturday, Sunday)
|
|
32
30
|
* new Chronos().isWeekend(1, 3);
|
|
31
|
+
*/
|
|
32
|
+
isWeekend(weekStartsOn?: Enumerate<7>, weekendLength?: NumberRange<1, 4>): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* @instance Checks if the current date falls on a weekend using indices of weekend days.
|
|
33
35
|
*
|
|
36
|
+
* @param weekendDays Optional. A tuple of custom weekend day indices (0–6). Can pass only 1-4 elements.
|
|
37
|
+
* @returns `true` if the current date is a weekend day according to the provided `weekendDays`; otherwise `false`.
|
|
38
|
+
*
|
|
39
|
+
* @description
|
|
40
|
+
* Determines whether the current date is considered part of the weekend.
|
|
41
|
+
*
|
|
42
|
+
* **Behavior:**
|
|
43
|
+
* - `weekendDays` is used directly as the weekend days instead of calculating from `weekStartsOn` + `weekendLength`.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
34
46
|
* // Fully custom weekend days (Sunday, Friday, Saturday)
|
|
35
|
-
* new Chronos().isWeekend(
|
|
47
|
+
* new Chronos().isWeekend([0, 5, 6]);
|
|
36
48
|
*/
|
|
37
|
-
isWeekend
|
|
49
|
+
isWeekend(weekendDays: RangeTuple<Enumerate<7>, 1, 4>): boolean;
|
|
38
50
|
/**
|
|
39
|
-
* @instance Checks if the current date is a workday (non-weekend day).
|
|
51
|
+
* @instance Checks if the current date is a workday (non-weekend day) using week start day and weekend length.
|
|
40
52
|
*
|
|
41
53
|
* @param weekStartsOn Optional. The day index (0–6) that the week starts on. Default is `0` (Sunday).
|
|
42
54
|
* @param weekendLength Optional. The number of consecutive days at the end of the week considered as weekend. Must be between 1 and 4. Default is `2`.
|
|
43
|
-
* @param weekendDays Optional. A tuple of custom weekend day indices (0–6). Its length must match `weekendLength`. If provided, this overrides `weekStartsOn` + `weekendLength` calculation.
|
|
44
55
|
* @returns `true` if the current date is a work day according to the provided parameters; otherwise `false`.
|
|
45
56
|
*
|
|
46
57
|
* @description
|
|
@@ -50,13 +61,25 @@ declare module '../Chronos' {
|
|
|
50
61
|
* - By default (`weekStartsOn = 0`, `weekendLength = 2`), Saturday (6) and Friday (5) are considered weekend.
|
|
51
62
|
* - `weekStartsOn` sets the start of the week for calculating weekend days.
|
|
52
63
|
* - `weekendLength` sets how many days at the end of the week are treated as weekend.
|
|
53
|
-
* - `weekendDays`, if provided, is used directly as the weekend days instead of calculating from `weekStartsOn` + `weekendLength`.
|
|
54
64
|
*/
|
|
55
|
-
isWorkday
|
|
65
|
+
isWorkday(weekStartsOn?: Enumerate<7>, weekendLength?: NumberRange<1, 4>): boolean;
|
|
56
66
|
/**
|
|
57
|
-
* @instance Checks if the current date
|
|
67
|
+
* @instance Checks if the current date is a workday (non-weekend day) using indices of weekend days.
|
|
68
|
+
*
|
|
69
|
+
* @param weekendDays A tuple of custom weekend day indices (0–6). Can pass only 1-4 elements.
|
|
70
|
+
* @returns `true` if the current date is a work day according to the provided `weekendDays`; otherwise `false`.
|
|
58
71
|
*
|
|
59
|
-
* @
|
|
72
|
+
* @description
|
|
73
|
+
* Determines whether the current date is considered as workday. Internally uses {@link isWeekend} method.
|
|
74
|
+
*
|
|
75
|
+
* **Behavior:**
|
|
76
|
+
* - `weekendDays` is used directly as the weekend days instead of calculating from `weekStartsOn` + `weekendLength`.
|
|
77
|
+
*/
|
|
78
|
+
isWorkday(weekendDays: RangeTuple<Enumerate<7>, 1, 4>): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* @instance Checks if the current date and time fall within business hours using week start day and weekend length & other options.
|
|
81
|
+
*
|
|
82
|
+
* @param options Options to configure business hour and weekends.
|
|
60
83
|
*
|
|
61
84
|
* @returns Whether the current time is within business hours.
|
|
62
85
|
*
|
|
@@ -65,23 +88,29 @@ declare module '../Chronos' {
|
|
|
65
88
|
* - Supports standard and overnight business hours. Overnight means `end < start`.
|
|
66
89
|
* - Example: `businessStartHour = 22`, `businessEndHour = 6` will cover 10 PM to 6 AM next day.
|
|
67
90
|
*
|
|
68
|
-
* * *Weekends are determined by `weekStartsOn` and `weekendLength`
|
|
91
|
+
* * *Weekends are determined by `weekStartsOn` and `weekendLength` using the {@link isWorkday} method.*
|
|
92
|
+
*/
|
|
93
|
+
isBusinessHour(options?: BusinessOptionsBasic): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* @instance Checks if the current date and time fall within business hours using indices of weekend days & other options.
|
|
96
|
+
*
|
|
97
|
+
* @param options Options to configure business hour and weekends.
|
|
69
98
|
*
|
|
70
|
-
*
|
|
71
|
-
* ```ts
|
|
72
|
-
* new Chronos().isBusinessHour<3>({ weekendDays: [0, 2, 4] });
|
|
99
|
+
* @returns Whether the current time is within business hours.
|
|
73
100
|
*
|
|
74
|
-
*
|
|
101
|
+
* @remarks
|
|
102
|
+
* - Business hours are typically 9 AM to 5 PM on weekdays.
|
|
103
|
+
* - Supports standard and overnight business hours. Overnight means `end < start`.
|
|
104
|
+
* - Example: `businessStartHour = 22`, `businessEndHour = 6` will cover 10 PM to 6 AM next day.
|
|
75
105
|
*
|
|
76
|
-
*
|
|
77
|
-
* ```
|
|
106
|
+
* * *Weekends are determined by `weekendDays` tuple using the {@link isWorkday} method.*
|
|
78
107
|
*/
|
|
79
|
-
isBusinessHour
|
|
108
|
+
isBusinessHour(options?: BusinessOptionsWeekends): boolean;
|
|
80
109
|
/**
|
|
81
110
|
* @instance Returns the academic year based on a typical start in July and end in June.
|
|
82
111
|
* @returns The academic year in format `YYYY-YYYY`.
|
|
83
112
|
*/
|
|
84
|
-
toAcademicYear():
|
|
113
|
+
toAcademicYear(): AcademicYear;
|
|
85
114
|
/**
|
|
86
115
|
* @instance Returns the fiscal quarter based on custom fiscal year start (defaults to July).
|
|
87
116
|
* @param startMonth - The fiscal year start month (1-12), default is July (7).
|
package/dist/dts/date/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Enumerate, NumberRange } from '../number/types';
|
|
2
|
-
import type { LooseLiteral,
|
|
2
|
+
import type { LooseLiteral, RangeTuple } from '../utils/types';
|
|
3
3
|
import type { Chronos } from './Chronos';
|
|
4
4
|
import type { ChronosStatics } from './chronos-statics';
|
|
5
5
|
import type { DATE_FORMATS, DAY_FORMATS, DAYS, HOUR_FORMATS, MILLISECOND_FORMATS, MINUTE_FORMATS, MONTH_FORMATS, MONTHS, SECOND_FORMATS, TIME_FORMATS, TIME_ZONES, WESTERN_ZODIAC_SIGNS, YEAR_FORMATS, ZODIAC_PRESETS } from './constants';
|
|
@@ -76,27 +76,46 @@ type DateTimeConnector = ' ' | ', ' | '; ' | ' - ';
|
|
|
76
76
|
export type StrictFormat = LooseLiteral<DateParts | TimeParts | `${DateParts}${DateTimeConnector}${TimeParts}`>;
|
|
77
77
|
/** Iterable `Chronos` object properties */
|
|
78
78
|
export interface ChronosObject {
|
|
79
|
+
/** Full year (e.g., 2025). */
|
|
79
80
|
year: number;
|
|
81
|
+
/** Month index starting from 0 (January = 0). */
|
|
80
82
|
month: Enumerate<12>;
|
|
83
|
+
/** ISO month number starting from 1 (January = 1). */
|
|
81
84
|
isoMonth: NumberRange<1, 12>;
|
|
85
|
+
/** Day of the month (1–31). */
|
|
82
86
|
date: NumberRange<1, 31>;
|
|
87
|
+
/** Day of the week index (0–6, Sunday = 0). */
|
|
83
88
|
weekDay: Enumerate<7>;
|
|
89
|
+
/** ISO day of the week number (1–7, Monday = 1). */
|
|
84
90
|
isoWeekDay: NumberRange<1, 7>;
|
|
91
|
+
/** Hour of the day (0–23). */
|
|
85
92
|
hour: Enumerate<24>;
|
|
93
|
+
/** Minute of the hour (0–59). */
|
|
86
94
|
minute: Enumerate<60>;
|
|
95
|
+
/** Second of the minute (0–59). */
|
|
87
96
|
second: Enumerate<60>;
|
|
97
|
+
/** Milliseconds within the second. */
|
|
88
98
|
millisecond: Milliseconds;
|
|
99
|
+
/** Timestamp in milliseconds since the Unix epoch. */
|
|
89
100
|
timestamp: number;
|
|
101
|
+
/** Unix timestamp in seconds since the epoch. */
|
|
90
102
|
unix: number;
|
|
91
103
|
}
|
|
92
104
|
/** Return object type of `duration` method of `Chronos`. */
|
|
93
105
|
export interface TimeDuration {
|
|
106
|
+
/** Total number of years. */
|
|
94
107
|
years: number;
|
|
108
|
+
/** Number of months remaining after full years are counted. */
|
|
95
109
|
months: number;
|
|
110
|
+
/** Number of days remaining after full months are counted. */
|
|
96
111
|
days: number;
|
|
112
|
+
/** Number of hours remaining after full days are counted. */
|
|
97
113
|
hours: number;
|
|
114
|
+
/** Number of minutes remaining after full hours are counted. */
|
|
98
115
|
minutes: number;
|
|
116
|
+
/** Number of seconds remaining after full minutes are counted. */
|
|
99
117
|
seconds: number;
|
|
118
|
+
/** Number of milliseconds remaining after full seconds are counted. */
|
|
100
119
|
milliseconds: number;
|
|
101
120
|
}
|
|
102
121
|
/** Interface for accessing internal private properties in extended `Chronos` class */
|
|
@@ -184,6 +203,8 @@ export type DayPart = 'night' | 'midnight' | 'lateNight' | 'morning' | 'afternoo
|
|
|
184
203
|
export type DayPartConfig = Record<DayPart, [ClockHour, ClockHour]>;
|
|
185
204
|
/** Quarters of the year */
|
|
186
205
|
export type Quarter = 1 | 2 | 3 | 4;
|
|
206
|
+
/** Academic year, e.g. `2024-2025` */
|
|
207
|
+
export type AcademicYear = `${number}-${number}`;
|
|
187
208
|
/** Names of Zodiac signs */
|
|
188
209
|
export type ZodiacSign = (typeof WESTERN_ZODIAC_SIGNS)[number][0];
|
|
189
210
|
/** Presets for Zodiac Sign Configuration */
|
|
@@ -329,19 +350,26 @@ export interface SeasonOptions {
|
|
|
329
350
|
}
|
|
330
351
|
/** * A plugin that augments the Chronos class with methods or properties. */
|
|
331
352
|
export type ChronosPlugin = (ChronosClass: $Chronos) => void;
|
|
332
|
-
|
|
333
|
-
export interface BusinessHourOptions<Length extends NumberRange<1, 4>> {
|
|
353
|
+
export interface $BusinessHourBaseOptions {
|
|
334
354
|
/** - Optional starting hour of business time (0–23). Defaults to `9` (9 AM). */
|
|
335
355
|
businessStartHour?: Enumerate<24>;
|
|
336
356
|
/** - Optional ending hour of business time (0–23). Defaults to `17` (5 PM). */
|
|
337
357
|
businessEndHour?: Enumerate<24>;
|
|
358
|
+
}
|
|
359
|
+
/** Options for configuring business hour with `weekStartsOn` and `weekendLength` */
|
|
360
|
+
export interface BusinessOptionsBasic extends $BusinessHourBaseOptions {
|
|
338
361
|
/** - Optional day the week starts on (0–6). Default is `0` (Sunday). */
|
|
339
|
-
weekStartsOn?: Enumerate<7
|
|
340
|
-
/** - Optional weekend length (1
|
|
341
|
-
weekendLength?:
|
|
342
|
-
/** - Tuple of indices of weekend days. Default is `undefined`. */
|
|
343
|
-
weekendDays?: TupleOf<Enumerate<7>, Length>;
|
|
362
|
+
weekStartsOn?: Enumerate<7> | undefined;
|
|
363
|
+
/** - Optional weekend length (1-4). Default is `2`.*/
|
|
364
|
+
weekendLength?: NumberRange<1, 4> | undefined;
|
|
344
365
|
}
|
|
366
|
+
/** Options for configuring business hour with `weekendDays` tuple */
|
|
367
|
+
export interface BusinessOptionsWeekends extends $BusinessHourBaseOptions {
|
|
368
|
+
/** - Tuple of indices (0-6) of weekend days. Can pass only 1-4 elements. Default is `undefined`. */
|
|
369
|
+
weekendDays?: RangeTuple<Enumerate<7>, 1, 4> | undefined;
|
|
370
|
+
}
|
|
371
|
+
/** Options for configuring business hour */
|
|
372
|
+
export type $BusinessHourOptions = BusinessOptionsBasic | BusinessOptionsWeekends;
|
|
345
373
|
/** Interface representing a date-like object. */
|
|
346
374
|
export interface DateLike {
|
|
347
375
|
toJSON?(): string;
|
|
@@ -241,6 +241,18 @@ export type TupleToUnion<T extends readonly unknown[]> = T[number];
|
|
|
241
241
|
* type EmptyTuple = TupleOf<boolean, 0>; // []
|
|
242
242
|
*/
|
|
243
243
|
export type TupleOf<T, N extends number, R extends unknown[] = []> = R['length'] extends N ? R : TupleOf<T, N, [...R, T]>;
|
|
244
|
+
/** * Build a tuple of given length (helper for type-level arithmetic). */
|
|
245
|
+
export type $BuildTuple<L extends number, T extends unknown[] = []> = T['length'] extends L ? T : $BuildTuple<L, [...T, unknown]>;
|
|
246
|
+
/** * Produce a union of numbers `From | From+1 | ... | To`. */
|
|
247
|
+
export type $Range<From extends number, To extends number, Arr extends unknown[] = $BuildTuple<From>, Result = never> = Arr['length'] extends To ? Result | To : $Range<From, To, [...Arr, unknown], Result | Arr['length']>;
|
|
248
|
+
/**
|
|
249
|
+
* * Creates a tuple with length between `Min` and `Max` (inclusive).
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* type Ranged = RangeTuple<string, 2, 4>;
|
|
253
|
+
* // Ranged -> [string, string] | [string, string, string] | [string, string, string, string]
|
|
254
|
+
*/
|
|
255
|
+
export type RangeTuple<T, Min extends number, Max extends number> = $Range<Min, Max> extends infer N ? N extends number ? TupleOf<T, N> : never : never;
|
|
244
256
|
/**
|
|
245
257
|
* * Makes selected or all properties of an object type optional (only the values, not the keys).
|
|
246
258
|
*
|
|
@@ -262,7 +274,7 @@ export type TupleOf<T, N extends number, R extends unknown[] = []> = R['length']
|
|
|
262
274
|
export type ValueOptional<O, K extends keyof O = keyof O> = {
|
|
263
275
|
[P in keyof O]: P extends K ? O[P] | undefined : O[P];
|
|
264
276
|
};
|
|
265
|
-
type $Without<T, U> = {
|
|
277
|
+
export type $Without<T, U> = {
|
|
266
278
|
[P in Exclude<keyof T, keyof U>]?: never;
|
|
267
279
|
};
|
|
268
280
|
/**
|
|
@@ -366,14 +378,12 @@ export type RemoveNever<T> = {
|
|
|
366
378
|
export type RenameKeys<T, R extends Partial<Record<keyof T, string>>> = {
|
|
367
379
|
[K in keyof T as K extends keyof R ? Extract<R[K], string | number | symbol> : K]: T[K];
|
|
368
380
|
};
|
|
369
|
-
/** * Build a tuple of given length (helper for type-level arithmetic). */
|
|
370
|
-
export type BuildTuple<L extends number, T extends unknown[] = []> = T['length'] extends L ? T : BuildTuple<L, [...T, unknown]>;
|
|
371
381
|
/** * Subtracts `B` from `A` (helper for type-level arithmetic). */
|
|
372
|
-
export type Subtract<A extends number, B extends number> = [
|
|
373
|
-
|
|
374
|
-
] extends [
|
|
382
|
+
export type $Subtract<A extends number, B extends number> = [
|
|
383
|
+
...$BuildTuple<A>
|
|
384
|
+
] extends [...$BuildTuple<B>, ...infer R] ? R['length'] : never;
|
|
375
385
|
/** * Forbids all properties not in `K`. */
|
|
376
|
-
export type Forbid<T, K extends keyof T> = {
|
|
386
|
+
export type $Forbid<T, K extends keyof T> = {
|
|
377
387
|
[P in Exclude<keyof T, K>]?: never;
|
|
378
388
|
};
|
|
379
389
|
/**
|
|
@@ -405,7 +415,7 @@ export type Forbid<T, K extends keyof T> = {
|
|
|
405
415
|
export type RequireAtLeast<T extends GenericObject, N extends number, Keys extends keyof T = keyof T> = N extends 1 ? {
|
|
406
416
|
[K in Keys]-?: Required<Pick<T, K>> & Partial<Omit<T, K>>;
|
|
407
417
|
}[Keys] : {
|
|
408
|
-
[K in Keys]-?: Required<Pick<T, K>> & RequireAtLeast<Omit<T, K>, Subtract<N, 1>>;
|
|
418
|
+
[K in Keys]-?: Required<Pick<T, K>> & RequireAtLeast<Omit<T, K>, $Subtract<N, 1>>;
|
|
409
419
|
}[Keys];
|
|
410
420
|
/**
|
|
411
421
|
* * Enforces that exactly `N` properties of type `T` are required.
|
|
@@ -436,7 +446,7 @@ export type RequireAtLeast<T extends GenericObject, N extends number, Keys exten
|
|
|
436
446
|
* const c6: TwoExact = { host: "a", port: 1, secure: true }; // ❌ Error
|
|
437
447
|
*/
|
|
438
448
|
export type RequireExactly<T extends GenericObject, N extends number> = {
|
|
439
|
-
[K in keyof T]: Required<Pick<T, K>> & (N extends 1 ? Forbid<T, K> : RequireExactly<Omit<T, K>, Subtract<N, 1>>);
|
|
449
|
+
[K in keyof T]: Required<Pick<T, K>> & (N extends 1 ? $Forbid<T, K> : RequireExactly<Omit<T, K>, $Subtract<N, 1>>);
|
|
440
450
|
}[keyof T];
|
|
441
451
|
/**
|
|
442
452
|
* * Enforces that between `Min` and `Max` properties of type `T` are required.
|
|
@@ -459,7 +469,7 @@ export type RequireExactly<T extends GenericObject, N extends number> = {
|
|
|
459
469
|
* const s3: OneOrTwo = { theme: "dark", lang: "en", debug: true }; // ❌ (3 keys)
|
|
460
470
|
* const s4: OneOrTwo = {}; // ❌ (0 keys)
|
|
461
471
|
*/
|
|
462
|
-
export type RequireBetween<T extends GenericObject, Min extends number, Max extends number, C extends unknown[] = BuildTuple<Max>, Acc extends unknown[] = BuildTuple<Min>> = RequireExactly<T, Acc['length']> | (Acc['length'] extends Max ? never : RequireBetween<T, Min, Max, C, [...Acc, unknown]>);
|
|
472
|
+
export type RequireBetween<T extends GenericObject, Min extends number, Max extends number, C extends unknown[] = $BuildTuple<Max>, Acc extends unknown[] = $BuildTuple<Min>> = RequireExactly<T, Acc['length']> | (Acc['length'] extends Max ? never : RequireBetween<T, Min, Max, C, [...Acc, unknown]>);
|
|
463
473
|
/**
|
|
464
474
|
* * Cast one type to another while preserving compatibility.
|
|
465
475
|
*
|
package/dist/esm/date/Chronos.js
CHANGED
|
@@ -201,19 +201,20 @@ export class Chronos {
|
|
|
201
201
|
}
|
|
202
202
|
#normalizeDuration(result, absolute, isFuture) {
|
|
203
203
|
const entries = Object.entries(result);
|
|
204
|
+
const updated = {};
|
|
204
205
|
if (!absolute && !isFuture) {
|
|
205
206
|
for (const [key, value] of entries) {
|
|
206
207
|
if (value !== 0) {
|
|
207
|
-
|
|
208
|
+
updated[key] = value * -1;
|
|
208
209
|
}
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
212
|
else if (absolute) {
|
|
212
213
|
for (const [key, value] of entries) {
|
|
213
|
-
|
|
214
|
+
updated[key] = Math.abs(value);
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
|
-
return
|
|
217
|
+
return updated;
|
|
217
218
|
}
|
|
218
219
|
get year() {
|
|
219
220
|
return this.#date.getFullYear();
|
|
@@ -1,34 +1,42 @@
|
|
|
1
1
|
import { isValidArray } from '../../guards/non-primitives.js';
|
|
2
|
+
import { isUndefined } from '../../guards/primitives.js';
|
|
2
3
|
import { INTERNALS } from '../constants.js';
|
|
3
4
|
export const businessPlugin = (ChronosClass) => {
|
|
4
5
|
const internalDate = ChronosClass[INTERNALS].internalDate;
|
|
5
|
-
ChronosClass.prototype.isWeekend = function (
|
|
6
|
+
ChronosClass.prototype.isWeekend = function (determiner = 0, weekendLength = 2) {
|
|
6
7
|
const day = internalDate(this).getDay();
|
|
7
|
-
if (isValidArray(
|
|
8
|
-
return
|
|
8
|
+
if (isValidArray(determiner)) {
|
|
9
|
+
return determiner.includes(day);
|
|
9
10
|
}
|
|
10
|
-
const lastDayOfWeek = (
|
|
11
|
+
const lastDayOfWeek = (determiner + 6) % 7;
|
|
11
12
|
const computedWeekendDays = Array.from({ length: weekendLength }, (_, i) => (lastDayOfWeek - i + 7) % 7);
|
|
12
13
|
return computedWeekendDays.includes(day);
|
|
13
14
|
};
|
|
14
|
-
ChronosClass.prototype.isWorkday = function (
|
|
15
|
-
|
|
15
|
+
ChronosClass.prototype.isWorkday = function (determiner = 0, weekendLength = 2) {
|
|
16
|
+
if (isValidArray(determiner)) {
|
|
17
|
+
return !this.isWeekend(determiner);
|
|
18
|
+
}
|
|
19
|
+
return !this.isWeekend(determiner, weekendLength);
|
|
16
20
|
};
|
|
17
21
|
ChronosClass.prototype.isBusinessHour = function (options) {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
const _isBusinessHour = () => {
|
|
23
|
+
const { businessStartHour = 9, businessEndHour = 17 } = options ?? {};
|
|
24
|
+
if (businessStartHour === businessEndHour) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const hour = internalDate(this).getHours();
|
|
28
|
+
if (businessStartHour < businessEndHour) {
|
|
29
|
+
return hour >= businessStartHour && hour < businessEndHour;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return hour >= businessStartHour || hour < businessEndHour;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
if (options && 'weekendDays' in options && !isUndefined(options?.weekendDays)) {
|
|
36
|
+
return this.isWorkday(options?.weekendDays) && _isBusinessHour();
|
|
31
37
|
}
|
|
38
|
+
const { weekStartsOn = 0, weekendLength = 2 } = (options ?? {});
|
|
39
|
+
return this.isWorkday(weekStartsOn, weekendLength) && _isBusinessHour();
|
|
32
40
|
};
|
|
33
41
|
ChronosClass.prototype.toFiscalQuarter = function (startMonth = 7) {
|
|
34
42
|
const month = internalDate(this).getMonth() + 1;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nhb-toolbox",
|
|
3
|
-
"version": "4.20.
|
|
3
|
+
"version": "4.20.80",
|
|
4
4
|
"description": "A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|