small date utilities
22 kB
804 lines
1/**
2 * represents a day of the week as a numeric value (0 = Sunday, 6 = Saturday).
3 */
4export type DayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6;
5
6/**
7 * returns the Unix timestamp in milliseconds for a given date.
8 * @param date the date to convert.
9 * @returns the Unix timestamp in milliseconds.
10 */
11/*#__NO_SIDE_EFFECTS__*/
12export const toUnixMilliseconds = (date: Date): number => {
13 return date.getTime();
14};
15
16/**
17 * returns the Unix timestamp in seconds for a given date
18 * @param date the date to convert.
19 * @returns the Unix timestamp in seconds.
20 */
21/*#__NO_SIDE_EFFECTS__*/
22export const toUnixSeconds = (date: Date): number => {
23 return Math.floor(toUnixMilliseconds(date) / 1_000);
24};
25
26/**
27 * converts a date to an ISO 8601 date string (YYYY-MM-DD) in local timezone
28 * @param date the date to format
29 * @returns the formatted date string
30 */
31/*#__NO_SIDE_EFFECTS__*/
32export const toISODateString = (date: Date): string => {
33 return date.toLocaleDateString('sv-SE');
34};
35
36/**
37 * converts a date to an ISO 8601 datetime string (YYYY-MM-DDTHH:mm:ss.sss) in local timezone
38 * @param date the date to format
39 * @returns the formatted datetime string
40 */
41/*#__NO_SIDE_EFFECTS__*/
42export const toISODateTimeString = (date: Date): string => {
43 return date.toLocaleString('sv-SE').replace(' ', 'T') + '.' + ('' + getMilliseconds(date)).padStart(3, '0');
44};
45
46/**
47 * returns the milliseconds portion of a given date.
48 * @param date the date to extract from.
49 * @returns the milliseconds portion of the date.
50 */
51/*#__NO_SIDE_EFFECTS__*/
52export const getMilliseconds = (date: Date): number => {
53 return date.getMilliseconds();
54};
55
56/**
57 * returns the milliseconds portion of a given date in UTC.
58 * @param date the date to extract from.
59 * @returns the milliseconds portion of the date.
60 */
61/*#__NO_SIDE_EFFECTS__*/
62export const getUtcMilliseconds = (date: Date): number => {
63 return date.getUTCMilliseconds();
64};
65
66/**
67 * returns the seconds portion of a given date.
68 * @param date the date to extract from.
69 * @returns the seconds portion of the date.
70 */
71/*#__NO_SIDE_EFFECTS__*/
72export const getSeconds = (date: Date): number => {
73 return date.getSeconds();
74};
75
76/**
77 * returns the seconds portion of a given date in UTC.
78 * @param date the date to extract from.
79 * @returns the seconds portion of the date.
80 */
81/*#__NO_SIDE_EFFECTS__*/
82export const getUtcSeconds = (date: Date): number => {
83 return date.getUTCSeconds();
84};
85
86/**
87 * returns the minutes portion of a given date.
88 * @param date the date to extract from.
89 * @returns the minutes portion of the date.
90 */
91/*#__NO_SIDE_EFFECTS__*/
92export const getMinutes = (date: Date): number => {
93 return date.getMinutes();
94};
95
96/**
97 * returns the minutes portion of a given date in UTC.
98 * @param date the date to extract from.
99 * @returns the minutes portion of the date.
100 */
101/*#__NO_SIDE_EFFECTS__*/
102export const getUtcMinutes = (date: Date): number => {
103 return date.getUTCMinutes();
104};
105
106/**
107 * returns the hours portion of a given date.
108 * @param date the date to extract from.
109 * @returns the hours portion of the date.
110 */
111/*#__NO_SIDE_EFFECTS__*/
112export const getHours = (date: Date): number => {
113 return date.getHours();
114};
115
116/**
117 * returns the hours portion of a given date in UTC.
118 * @param date the date to extract from.
119 * @returns the hours portion of the date.
120 */
121/*#__NO_SIDE_EFFECTS__*/
122export const getUtcHours = (date: Date): number => {
123 return date.getUTCHours();
124};
125
126/**
127 * returns the day of the week for a given date (0 = Sunday, 6 = Saturday).
128 * @param date the date to extract from.
129 * @returns the day of the week as a number.
130 */
131/*#__NO_SIDE_EFFECTS__*/
132export const getDayOfWeek = (date: Date): DayOfWeek => {
133 return date.getDay() as DayOfWeek;
134};
135
136/**
137 * returns the day of the week for a given date in UTC (0 = Sunday, 6 = Saturday).
138 * @param date the date to extract from.
139 * @returns the day of the week as a number.
140 */
141/*#__NO_SIDE_EFFECTS__*/
142export const getUtcDayOfWeek = (date: Date): DayOfWeek => {
143 return date.getUTCDay() as DayOfWeek;
144};
145
146/**
147 * returns the day of the month for a given date.
148 * @param date the date to extract from.
149 * @returns the day of the month as a number.
150 */
151/*#__NO_SIDE_EFFECTS__*/
152export const getDayOfMonth = (date: Date): number => {
153 return date.getDate();
154};
155
156/**
157 * returns the day of the month for a given date in UTC.
158 * @param date the date to extract from.
159 * @returns the day of the month as a number.
160 */
161/*#__NO_SIDE_EFFECTS__*/
162export const getUtcDayOfMonth = (date: Date): number => {
163 return date.getUTCDate();
164};
165
166/**
167 * returns the month portion of a given date (0 = January, 11 = December).
168 * @param date the date to extract from.
169 * @returns the month as a number.
170 */
171/*#__NO_SIDE_EFFECTS__*/
172export const getMonth = (date: Date): number => {
173 return date.getMonth();
174};
175
176/**
177 * returns the month portion of a given date in UTC (0 = January, 11 = December).
178 * @param date the date to extract from.
179 * @returns the month as a number.
180 */
181/*#__NO_SIDE_EFFECTS__*/
182export const getUtcMonth = (date: Date): number => {
183 return date.getUTCMonth();
184};
185
186/**
187 * returns the year portion of a given date.
188 * @param date the date to extract from.
189 * @returns the year as a number.
190 */
191/*#__NO_SIDE_EFFECTS__*/
192export const getYear = (date: Date): number => {
193 return date.getFullYear();
194};
195
196/**
197 * returns the year portion of a given date in UTC.
198 * @param date the date to extract from.
199 * @returns the year as a number.
200 */
201/*#__NO_SIDE_EFFECTS__*/
202export const getUtcYear = (date: Date): number => {
203 return date.getUTCFullYear();
204};
205
206/**
207 * compares two dates and returns a number indicating their relative order,
208 * in UTC time.
209 * @template TDate
210 * @param a the first date to compare.
211 * @param b the second date to compare.
212 * @returns -1 if a is before b, 1 if a is after b, or 0 if they are equal.
213 */
214/*#__NO_SIDE_EFFECTS__*/
215export const compareUtcAsc = <TDate extends Date>(a: TDate, b: TDate): number => {
216 const aMs = toUnixMilliseconds(a);
217 const bMs = toUnixMilliseconds(b);
218
219 if (aMs < bMs) {
220 return -1;
221 }
222 if (aMs > bMs) {
223 return 1;
224 }
225 return 0;
226};
227
228/**
229 * compares two dates and returns a number indicating their relative order,
230 * in local time.
231 * @template TDate
232 * @param a the first date to compare.
233 * @param b the second date to compare.
234 * @returns -1 if a is before b, 1 if a is after b, or 0 if they are equal.
235 */
236/*#__NO_SIDE_EFFECTS__*/
237export const compareLocalAsc = <TDate extends Date>(a: TDate, b: TDate): number => {
238 const diff = getMilliseconds(a) - getMilliseconds(b) ||
239 getSeconds(a) - getSeconds(b) ||
240 getMinutes(a) - getMinutes(b) ||
241 getHours(a) - getHours(b) ||
242 getDayOfMonth(a) - getDayOfMonth(b) ||
243 getMonth(a) - getMonth(b) ||
244 getYear(a) - getYear(b);
245
246 if (diff < 0) {
247 return -1;
248 }
249 if (diff > 0) {
250 return 1;
251 }
252 return 0;
253};
254
255/**
256 * checks if a date is before another date.
257 * @template TDate
258 * @param a the date to compare.
259 * @param b the date to compare against.
260 * @returns true if first date is before the second, false otherwise.
261 */
262/*#__NO_SIDE_EFFECTS__*/
263export const isBeforeDate = <TDate extends Date>(a: TDate, b: TDate): boolean => {
264 return a !== b && toUnixMilliseconds(a) < toUnixMilliseconds(b);
265};
266
267/**
268 * checks if a date is after another date.
269 * @template TDate
270 * @param a the date to compare.
271 * @param b the date to compare against.
272 * @returns true if the first date is after the second, false otherwise.
273 */
274/*#__NO_SIDE_EFFECTS__*/
275export const isAfterDate = <TDate extends Date>(a: TDate, b: TDate): boolean => {
276 return a !== b && toUnixMilliseconds(a) > toUnixMilliseconds(b);
277};
278
279/**
280 * checks if two dates are exactly the same.
281 * @template TDate
282 * @param a the first date to compare.
283 * @param b the second date to compare.
284 * @returns true if the two dates are the same, false otherwise.
285 */
286/*#__NO_SIDE_EFFECTS__*/
287export const isSameDate = <TDate extends Date>(a: TDate, b: TDate): boolean => {
288 return a === b || toUnixMilliseconds(a) === toUnixMilliseconds(b);
289};
290
291/**
292 * checks if two dates fall on the same calendar day.
293 * @template TDate
294 * @param a the first date to compare.
295 * @param b the second date to compare.
296 * @returns true if the two dates fall on the same calendar day, false otherwise.
297 */
298/*#__NO_SIDE_EFFECTS__*/
299export const isSameCalendarDate = <TDate extends Date>(a: TDate, b: TDate): boolean => {
300 if (a === b) {
301 return true;
302 }
303 return (
304 getDayOfMonth(a) === getDayOfMonth(b) &&
305 getMonth(a) === getMonth(b) &&
306 getYear(a) === getYear(b)
307 );
308};
309
310/**
311 * checks if two dates fall in the same calendar month.
312 * @template TDate
313 * @param a the first date to compare.
314 * @param b the second date to compare.
315 * @returns true if the two dates are in the same month, false otherwise.
316 */
317/*#__NO_SIDE_EFFECTS__*/
318export const isSameCalendarMonth = <TDate extends Date>(a: TDate, b: TDate): boolean => {
319 if (a === b) {
320 return true;
321 }
322 return (
323 getMonth(a) === getMonth(b) &&
324 getYear(a) === getYear(b)
325 );
326};
327
328/**
329 * checks if two dates fall in the same calendar year.
330 * @template TDate
331 * @param a the first date to compare.
332 * @param b the second date to compare.
333 * @returns true if the two dates are in the same year, false otherwise.
334 */
335/*#__NO_SIDE_EFFECTS__*/
336export const isSameCalendarYear = <TDate extends Date>(a: TDate, b: TDate): boolean => {
337 if (a === b) {
338 return true;
339 }
340 return getYear(a) === getYear(b);
341};
342
343/**
344 * returns the earlier of two dates.
345 * @template TDate
346 * @param a the first date to compare.
347 * @param b the second date to compare.
348 * @returns the earlier of the two dates.
349 */
350/*#__NO_SIDE_EFFECTS__*/
351export const min = <TDate extends Date>(a: TDate, b: TDate): TDate => {
352 return isBeforeDate(a, b) ? a : b;
353};
354
355/**
356 * returns the later of two dates.
357 * @template TDate
358 * @param a the first date to compare.
359 * @param b the second date to compare.
360 * @returns the later of the two dates.
361 */
362/*#__NO_SIDE_EFFECTS__*/
363export const max = <TDate extends Date>(a: TDate, b: TDate): TDate => {
364 return isAfterDate(a, b) ? a : b;
365};
366
367/**
368 * clamps a date between a minimum and maximum range.
369 * @template TDate
370 * @param date the date to clamp.
371 * @param min the minimum allowable date.
372 * @param max the maximum allowable date.
373 * @returns the clamped date.
374 */
375/*#__NO_SIDE_EFFECTS__*/
376export const clamp = <TDate extends Date>(
377 date: TDate,
378 min: TDate | undefined,
379 max: TDate | undefined,
380): TDate => {
381 if (min !== undefined && isBeforeDate(date, min)) {
382 return min;
383 }
384
385 if (max !== undefined && isAfterDate(date, max)) {
386 return max;
387 }
388
389 return date;
390};
391
392/**
393 * calculates the difference in milliseconds between two dates.
394 * @template TDate
395 * @param a the first date.
396 * @param b the second date.
397 * @returns the difference in milliseconds.
398 */
399/*#__NO_SIDE_EFFECTS__*/
400export const differenceInMilliseconds = <TDate extends Date>(a: TDate, b: TDate): number => {
401 return toUnixMilliseconds(a) - toUnixMilliseconds(b);
402};
403
404/**
405 * calculates the difference in seconds between two dates.
406 * @template TDate
407 * @param a the first date.
408 * @param b the second date.
409 * @returns the difference in seconds.
410 */
411/*#__NO_SIDE_EFFECTS__*/
412export const differenceInSeconds = <TDate extends Date>(a: TDate, b: TDate): number => {
413 return Math.trunc(differenceInMilliseconds(a, b) / 1_000);
414};
415
416/**
417 * calculates the difference in minutes between two dates.
418 * @template TDate
419 * @param a the first date.
420 * @param b the second date.
421 * @returns the difference in minutes.
422 */
423/*#__NO_SIDE_EFFECTS__*/
424export const differenceInMinutes = <TDate extends Date>(a: TDate, b: TDate): number => {
425 return Math.trunc(differenceInMilliseconds(a, b) / 60_000);
426};
427
428/**
429 * calculates the difference in hours between two dates.
430 * @template TDate
431 * @param a the first date.
432 * @param b the second date.
433 * @returns the difference in hours.
434 */
435/*#__NO_SIDE_EFFECTS__*/
436export const differenceInHours = <TDate extends Date>(a: TDate, b: TDate): number => {
437 return Math.trunc(differenceInMilliseconds(a, b) / 3_600_000);
438};
439
440/**
441 * calculates the difference in days between two dates.
442 * @template TDate
443 * @param a the first date.
444 * @param b the second date.
445 * @returns the difference in days.
446 */
447/*#__NO_SIDE_EFFECTS__*/
448export const differenceInDays = <TDate extends Date>(a: TDate, b: TDate): number => {
449 return Math.trunc(differenceInMilliseconds(a, b) / 86_400_000);
450};
451
452/**
453 * calculates the difference in calendar days between two dates.
454 * @template TDate
455 * @param a the first date.
456 * @param b the second date.
457 * @returns the difference in calendar days.
458 */
459/*#__NO_SIDE_EFFECTS__*/
460export const differenceInCalendarDays = <TDate extends Date>(a: TDate, b: TDate): number => {
461 return differenceInDays(startOfDay(a), startOfDay(b));
462};
463
464/**
465 * calculates the difference in weeks between two dates.
466 * @template TDate
467 * @param a the first date.
468 * @param b the second date.
469 * @returns the difference in weeks.
470 */
471/*#__NO_SIDE_EFFECTS__*/
472export const differenceInWeeks = <TDate extends Date>(a: TDate, b: TDate): number => {
473 return Math.trunc(differenceInDays(a, b) / 7);
474};
475
476/**
477 * calculates the difference in calendar weeks between two dates.
478 * @template TDate
479 * @param a the first date.
480 * @param b the second date.
481 * @returns the difference in calendar weeks.
482 */
483/*#__NO_SIDE_EFFECTS__*/
484export const differenceInCalendarWeeks = <TDate extends Date>(a: TDate, b: TDate): number => {
485 return differenceInWeeks(startOfWeek(a), startOfWeek(b));
486};
487
488/**
489 * calculates the difference in months between two dates.
490 * @template TDate
491 * @param a the first date.
492 * @param b the second date.
493 * @returns the difference in months.
494 */
495/*#__NO_SIDE_EFFECTS__*/
496export const differenceInMonths = <TDate extends Date>(a: TDate, b: TDate): number => {
497 return (getYear(a) - getYear(b)) * 12 + (getMonth(a) - getMonth(b));
498};
499
500/**
501 * calculates the difference in calendar months between two dates.
502 * @template TDate
503 * @param a the first date.
504 * @param b the second date.
505 * @returns the difference in calendar months.
506 */
507/*#__NO_SIDE_EFFECTS__*/
508export const differenceInCalendarMonths = <TDate extends Date>(a: TDate, b: TDate): number => {
509 return differenceInMonths(startOfMonth(a), startOfMonth(b));
510};
511
512/**
513 * calculates the difference in years between two dates.
514 * @template TDate
515 * @param a the first date.
516 * @param b the second date.
517 * @returns the difference in years.
518 */
519/*#__NO_SIDE_EFFECTS__*/
520export const differenceInYears = <TDate extends Date>(a: TDate, b: TDate): number => {
521 return getYear(a) - getYear(b);
522};
523
524/**
525 * calculates the difference in calendar years between two dates.
526 * @template TDate
527 * @param a the first date.
528 * @param b the second date.
529 * @returns the difference in calendar years.
530 */
531/*#__NO_SIDE_EFFECTS__*/
532export const differenceInCalendarYears = <TDate extends Date>(a: TDate, b: TDate): number => {
533 return differenceInYears(startOfYear(a), startOfYear(b));
534};
535
536type DateConstructor<TDate extends Date> = { new (value: number | string | TDate): TDate };
537
538/**
539 * creates a copy of a given date.
540 * @template TDate
541 * @param date the date to clone.
542 * @returns a new date object with the same value as the input date.
543 */
544/*#__NO_SIDE_EFFECTS__*/
545export const cloneDate = <TDate extends Date>(date: TDate): TDate => {
546 return new (date.constructor as DateConstructor<TDate>)(date);
547};
548
549/**
550 * returns the start of the day for a given date.
551 * @template TDate
552 * @param date the date to find the start of the day for.
553 * @returns a new date set to the start of the day.
554 */
555/*#__NO_SIDE_EFFECTS__*/
556export const startOfDay = <TDate extends Date>(date: TDate): TDate => {
557 const d = cloneDate(date);
558
559 d.setHours(0, 0, 0, 0);
560 return d;
561};
562
563/**
564 * returns the end of the day for a given date.
565 * @template TDate
566 * @param date the date to find the end of the day for.
567 * @returns a new date set to the end of the day.
568 */
569/*#__NO_SIDE_EFFECTS__*/
570export const endOfDay = <TDate extends Date>(date: TDate): TDate => {
571 const d = cloneDate(date);
572
573 d.setHours(23, 59, 59, 999);
574 return d;
575};
576
577/**
578 * returns the start of the week for a given date.
579 * @template TDate
580 * @param date the date to find the start of the week for.
581 * @returns a new date set to the start of the week.
582 */
583/*#__NO_SIDE_EFFECTS__*/
584export const startOfWeek = <TDate extends Date>(date: TDate): TDate => {
585 const d = cloneDate(date);
586
587 d.setDate(getDayOfMonth(d) - getDayOfWeek(d));
588 d.setHours(0, 0, 0, 0);
589 return d;
590};
591
592/**
593 * returns the end of the week for a given date.
594 * @template TDate
595 * @param date the date to find the end of the week for.
596 * @returns a new date set to the end of the week.
597 */
598/*#__NO_SIDE_EFFECTS__*/
599export const endOfWeek = <TDate extends Date>(date: TDate): TDate => {
600 const d = cloneDate(date);
601
602 d.setDate(getDayOfMonth(d) + (6 - getDayOfWeek(d)));
603 d.setHours(23, 59, 59, 999);
604 return d;
605};
606
607/**
608 * returns the start of the month for a given date.
609 * @template TDate
610 * @param date the date to find the start of the month for.
611 * @returns a new date set to the start of the month.
612 */
613/*#__NO_SIDE_EFFECTS__*/
614export const startOfMonth = <TDate extends Date>(date: TDate): TDate => {
615 const d = cloneDate(date);
616
617 d.setDate(1);
618 d.setHours(0, 0, 0, 0);
619 return d;
620};
621
622/**
623 * returns the end of the month for a given date.
624 * @template TDate
625 * @param date the date to find the end of the month for.
626 * @returns a new date set to the end of the month.
627 */
628/*#__NO_SIDE_EFFECTS__*/
629export const endOfMonth = <TDate extends Date>(date: TDate): TDate => {
630 const d = cloneDate(date);
631
632 d.setMonth(getMonth(d) + 1, 0);
633 d.setHours(23, 59, 59, 999);
634 return d;
635};
636
637/**
638 * returns the start of the year for a given date.
639 * @template TDate
640 * @param date the date to find the start of the year for.
641 * @returns a new date set to the start of the year.
642 */
643/*#__NO_SIDE_EFFECTS__*/
644export const startOfYear = <TDate extends Date>(date: TDate): TDate => {
645 const d = cloneDate(date);
646
647 d.setMonth(0, 1);
648 d.setHours(0, 0, 0, 0);
649 return d;
650};
651
652/**
653 * returns the end of the year for a given date.
654 * @template TDate
655 * @param date the date to find the end of the year for.
656 * @returns a new date set to the end of the year.
657 */
658/*#__NO_SIDE_EFFECTS__*/
659export const endOfYear = <TDate extends Date>(date: TDate): TDate => {
660 const d = cloneDate(date);
661
662 d.setMonth(11, 31);
663 d.setHours(23, 59, 59, 999);
664 return d;
665};
666
667/**
668 * adds a specified number of milliseconds to a date.
669 * @template TDate
670 * @param date the date to add milliseconds to.
671 * @param milliseconds the number of milliseconds to add.
672 * @returns a new date with the added milliseconds.
673 */
674/*#__NO_SIDE_EFFECTS__*/
675export const addMilliseconds = <TDate extends Date>(date: TDate, milliseconds: number): TDate => {
676 const d = cloneDate(date);
677
678 d.setMilliseconds(getMilliseconds(d) + milliseconds);
679 return d;
680};
681
682/**
683 * adds a specified number of seconds to a date.
684 * @template TDate
685 * @param date the date to add seconds to.
686 * @param seconds the number of seconds to add.
687 * @returns a new date with the added seconds.
688 */
689/*#__NO_SIDE_EFFECTS__*/
690export const addSeconds = <TDate extends Date>(date: TDate, seconds: number): TDate => {
691 const d = cloneDate(date);
692
693 d.setSeconds(getSeconds(d) + seconds);
694 return d;
695};
696
697/**
698 * adds a specified number of minutes to a date.
699 * @template TDate
700 * @param date the date to add minutes to.
701 * @param minutes the number of minutes to add.
702 * @returns a new date with the added minutes.
703 */
704/*#__NO_SIDE_EFFECTS__*/
705export const addMinutes = <TDate extends Date>(date: TDate, minutes: number): TDate => {
706 const d = cloneDate(date);
707
708 d.setMinutes(getMinutes(d) + minutes);
709 return d;
710};
711
712/**
713 * adds a specified number of hours to a date.
714 * @template TDate
715 * @param date the date to add hours to.
716 * @param hours the number of hours to add.
717 * @returns a new date with the added hours.
718 */
719/*#__NO_SIDE_EFFECTS__*/
720export const addHours = <TDate extends Date>(date: TDate, hours: number): TDate => {
721 const d = cloneDate(date);
722
723 d.setHours(getHours(d) + hours);
724 return d;
725};
726
727/**
728 * adds a specified number of days to a date.
729 * @template TDate
730 * @param date the date to add days to.
731 * @param days the number of days to add.
732 * @returns a new date with the added days.
733 */
734/*#__NO_SIDE_EFFECTS__*/
735export const addDays = <TDate extends Date>(date: TDate, days: number): TDate => {
736 const d = cloneDate(date);
737
738 d.setDate(getDayOfMonth(d) + days);
739 return d;
740};
741
742/**
743 * adds a specified number of months to a date.
744 * @template TDate
745 * @param date the date to add months to.
746 * @param months the number of months to add.
747 * @returns a new date with the added months.
748 */
749/*#__NO_SIDE_EFFECTS__*/
750export const addMonths = <TDate extends Date>(date: TDate, months: number): TDate => {
751 const d = cloneDate(date);
752
753 d.setMonth(getMonth(d) + months);
754 return d;
755};
756
757/**
758 * adds a specified number of years to a date.
759 * @template TDate
760 * @param date the date to add years to.
761 * @param years the number of years to add.
762 * @returns a new date with the added years.
763 */
764/*#__NO_SIDE_EFFECTS__*/
765export const addYears = <TDate extends Date>(date: TDate, years: number): TDate => {
766 const d = cloneDate(date);
767
768 d.setFullYear(getYear(d) + years);
769 return d;
770};
771
772/**
773 * returns the previous occurrence of a specific day of the week.
774 * @template TDate
775 * @param date the starting date.
776 * @param day the target day of the week.
777 * @returns a new date set to the previous occurrence of the specified day.
778 */
779/*#__NO_SIDE_EFFECTS__*/
780export const previousDay = <TDate extends Date>(date: TDate, day: DayOfWeek): TDate => {
781 let delta = day - getDayOfWeek(date);
782 if (delta >= 0) {
783 delta -= 7;
784 }
785
786 return addDays(date, delta);
787};
788
789/**
790 * returns the next occurrence of a specific day of the week.
791 * @template TDate
792 * @param date the starting date.
793 * @param day the target day of the week.
794 * @returns a new date set to the next occurrence of the specified day.
795 */
796/*#__NO_SIDE_EFFECTS__*/
797export const nextDay = <TDate extends Date>(date: TDate, day: DayOfWeek): TDate => {
798 let delta = day - getDayOfWeek(date);
799 if (delta <= 0) {
800 delta += 7;
801 }
802
803 return addDays(date, delta);
804};