@lazerlen/legend-calendar 1.0.0

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.
Files changed (48) hide show
  1. package/.eslintrc.js +29 -0
  2. package/.turbo/turbo-build.log +19 -0
  3. package/.turbo/turbo-lint.log +14 -0
  4. package/.turbo/turbo-test.log +261 -0
  5. package/.turbo/turbo-typecheck.log +1 -0
  6. package/CHANGELOG.md +127 -0
  7. package/dist/index.d.mts +679 -0
  8. package/dist/index.d.ts +679 -0
  9. package/dist/index.js +2 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index.mjs +2 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/package.json +47 -0
  14. package/src/components/Calendar.stories.tsx +226 -0
  15. package/src/components/Calendar.tsx +224 -0
  16. package/src/components/CalendarItemDay.tsx +385 -0
  17. package/src/components/CalendarItemEmpty.tsx +30 -0
  18. package/src/components/CalendarItemWeekName.tsx +67 -0
  19. package/src/components/CalendarList.stories.tsx +326 -0
  20. package/src/components/CalendarList.tsx +373 -0
  21. package/src/components/CalendarRowMonth.tsx +62 -0
  22. package/src/components/CalendarRowWeek.tsx +46 -0
  23. package/src/components/CalendarThemeProvider.tsx +43 -0
  24. package/src/components/HStack.tsx +67 -0
  25. package/src/components/VStack.tsx +67 -0
  26. package/src/components/index.ts +108 -0
  27. package/src/developer/decorators.tsx +54 -0
  28. package/src/developer/loggginHandler.tsx +6 -0
  29. package/src/developer/useRenderCount.ts +7 -0
  30. package/src/helpers/dates.test.ts +567 -0
  31. package/src/helpers/dates.ts +163 -0
  32. package/src/helpers/functions.ts +327 -0
  33. package/src/helpers/numbers.ts +11 -0
  34. package/src/helpers/strings.ts +2 -0
  35. package/src/helpers/tokens.ts +71 -0
  36. package/src/helpers/types.ts +3 -0
  37. package/src/hooks/useCalendar.test.ts +381 -0
  38. package/src/hooks/useCalendar.ts +351 -0
  39. package/src/hooks/useCalendarList.test.ts +382 -0
  40. package/src/hooks/useCalendarList.tsx +291 -0
  41. package/src/hooks/useDateRange.test.ts +128 -0
  42. package/src/hooks/useDateRange.ts +94 -0
  43. package/src/hooks/useOptimizedDayMetadata.test.ts +582 -0
  44. package/src/hooks/useOptimizedDayMetadata.ts +93 -0
  45. package/src/hooks/useTheme.ts +14 -0
  46. package/src/index.ts +24 -0
  47. package/tsconfig.json +13 -0
  48. package/tsup.config.ts +15 -0
@@ -0,0 +1,567 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "bun:test";
2
+ import {
3
+ addDays as addDaysDateFns,
4
+ subDays as subDaysDateFns,
5
+ endOfMonth as endOfMonthDateFns,
6
+ startOfWeek as startOfWeekDateFns,
7
+ startOfMonth as startOfMonthDateFns,
8
+ addMonths as addMonthsDateFns,
9
+ subMonths as subMonthsDateFns,
10
+ getWeeksInMonth as getWeeksInMonthDateFns,
11
+ getWeekOfMonth as getWeekOfMonthDateFns,
12
+ } from "date-fns";
13
+
14
+ import {
15
+ addDays,
16
+ endOfMonth,
17
+ fromDateId,
18
+ addMonths,
19
+ subMonths,
20
+ startOfMonth,
21
+ subDays,
22
+ startOfWeek,
23
+ toDateId,
24
+ isWeekend,
25
+ differenceInMonths,
26
+ getWeeksInMonth,
27
+ getWeekOfMonth,
28
+ } from "@/helpers/dates";
29
+ import { range } from "@/helpers/numbers";
30
+ import { pipe } from "@/helpers/functions";
31
+
32
+ describe("toDateId: UTC time zone", () => {
33
+ beforeEach(() => {
34
+ process.env.TZ = "UTC";
35
+ });
36
+ afterEach(() => {
37
+ process.env.TZ = undefined;
38
+ });
39
+
40
+ it("January 1st, 2024", () => {
41
+ expect(toDateId(new Date("2024-01-01T00:00:00.000Z"))).toBe("2024-01-01");
42
+ });
43
+ it("January 31th, 2024", () => {
44
+ expect(toDateId(new Date("2024-01-31T00:00:00.000Z"))).toBe("2024-01-31");
45
+ });
46
+ it("February 1st, 2024", () => {
47
+ expect(toDateId(new Date("2024-02-01T00:00:00.000Z"))).toBe("2024-02-01");
48
+ });
49
+ it("February 10th, 2024", () => {
50
+ expect(toDateId(new Date("2024-02-10T00:00:00.000Z"))).toBe("2024-02-10");
51
+ });
52
+ it("convert between ID -> Date -> ID returns the original result", () => {
53
+ const id = "2024-02-01";
54
+ const date = new Date(id);
55
+ expect(toDateId(date)).toBe(id);
56
+ });
57
+ });
58
+
59
+ describe("toDateId: Brasilia time zone ", () => {
60
+ beforeEach(() => {
61
+ process.env.TZ = "America/Sao_Paulo";
62
+ });
63
+ afterEach(() => {
64
+ process.env.TZ = undefined;
65
+ });
66
+
67
+ it("January 1st, 2024", () => {
68
+ expect(toDateId(new Date("2024-01-01T03:00:00.000Z"))).toBe("2024-01-01");
69
+ });
70
+ it("January 31th, 2024", () => {
71
+ expect(toDateId(new Date("2024-01-31T03:00:00.000Z"))).toBe("2024-01-31");
72
+
73
+ const january = new Date("2024-01-01T03:00:00.000Z");
74
+ const endOfJanuary = endOfMonth(january);
75
+ expect(toDateId(endOfJanuary)).toBe("2024-01-31");
76
+ });
77
+ it("February 1st, 2024", () => {
78
+ expect(toDateId(new Date("2024-02-01T03:00:00.000Z"))).toBe("2024-02-01");
79
+ });
80
+ it("February 10th, 2024", () => {
81
+ expect(toDateId(new Date("2024-02-10T03:00:00.000Z"))).toBe("2024-02-10");
82
+ });
83
+
84
+ it("February 29th, 2024", () => {
85
+ const february = new Date("2024-02-01T03:00:00.000Z");
86
+ const endOfFebruary = endOfMonth(february);
87
+ expect(toDateId(endOfFebruary)).toBe("2024-02-29");
88
+ });
89
+
90
+ it("convert between ID -> Date -> ID returns the original result", () => {
91
+ const id = "2024-02-01T03:00:00.000Z";
92
+ const date = new Date(id);
93
+ expect(toDateId(date)).toBe(id.split("T")[0]);
94
+ });
95
+ });
96
+
97
+ describe("fromDateId: UTC time zone", () => {
98
+ it("parse Jan 1st", () => {
99
+ const parsedDate = fromDateId("2024-01-01");
100
+ expect(parsedDate.getFullYear()).toBe(2024);
101
+ expect(parsedDate.getMonth()).toBe(0);
102
+ expect(parsedDate.getDate()).toBe(1);
103
+ expect(toDateId(parsedDate)).toBe("2024-01-01");
104
+ });
105
+
106
+ it("parses March 1st", () => {
107
+ const parsedDate = fromDateId("2024-03-01");
108
+ expect(toDateId(parsedDate)).toBe("2024-03-01");
109
+ });
110
+ });
111
+
112
+ describe("fromDateId: Brasilia time zone", () => {
113
+ beforeEach(() => {
114
+ process.env.TZ = "America/Sao_Paulo";
115
+ });
116
+ afterEach(() => {
117
+ process.env.TZ = undefined;
118
+ });
119
+
120
+ it("parse Jan 1st", () => {
121
+ const parsedDate = fromDateId("2024-01-01");
122
+ expect(parsedDate.getFullYear()).toBe(2024);
123
+ expect(parsedDate.getMonth()).toBe(0);
124
+ expect(parsedDate.getDate()).toBe(1);
125
+ expect(toDateId(parsedDate)).toBe("2024-01-01");
126
+ });
127
+
128
+ it("parses March 1st", () => {
129
+ const parsedDate = fromDateId("2024-03-01");
130
+ expect(toDateId(parsedDate)).toBe("2024-03-01");
131
+ });
132
+ });
133
+
134
+ describe("startOfMonth", () => {
135
+ it("January", () => {
136
+ expect(toDateId(startOfMonth(fromDateId("2024-01-02")))).toBe("2024-01-01");
137
+ expect(toDateId(startOfMonth(fromDateId("2024-01-31")))).toBe("2024-01-01");
138
+ });
139
+ it("February", () => {
140
+ expect(toDateId(startOfMonth(fromDateId("2024-02-01")))).toBe("2024-02-01");
141
+ expect(toDateId(startOfMonth(fromDateId("2024-02-29")))).toBe("2024-02-01");
142
+ });
143
+ it("matches date-fns", () => {
144
+ const baseDate = fromDateId("2020-01-01");
145
+ range(1, 1000).forEach((i) => {
146
+ const date = addDays(baseDate, i);
147
+ expect(startOfMonthDateFns(date).toISOString()).toBe(
148
+ startOfMonth(date).toISOString()
149
+ );
150
+ expect(startOfMonthDateFns(date).toISOString()).toBe(
151
+ startOfMonth(date).toISOString()
152
+ );
153
+ });
154
+ });
155
+ });
156
+
157
+ describe("endOfMonth", () => {
158
+ it("January", () => {
159
+ expect(toDateId(endOfMonth(fromDateId("2024-01-02")))).toBe("2024-01-31");
160
+ expect(toDateId(endOfMonth(fromDateId("2024-01-31")))).toBe("2024-01-31");
161
+ });
162
+ it("February", () => {
163
+ expect(toDateId(endOfMonth(fromDateId("2024-02-01")))).toBe("2024-02-29");
164
+ expect(toDateId(endOfMonth(fromDateId("2024-02-29")))).toBe("2024-02-29");
165
+ });
166
+ it("matches date-fns", () => {
167
+ const baseDate = fromDateId("2020-01-01");
168
+ range(1, 1000).forEach((i) => {
169
+ const date = addDays(baseDate, i);
170
+ expect(endOfMonthDateFns(date).toISOString()).toBe(
171
+ endOfMonth(date).toISOString()
172
+ );
173
+ expect(endOfMonthDateFns(date).toISOString()).toBe(
174
+ endOfMonth(date).toISOString()
175
+ );
176
+ });
177
+ });
178
+ });
179
+
180
+ describe("startOfWeek", () => {
181
+ it("sunday: week of February 17th", () => {
182
+ expect(toDateId(startOfWeek(fromDateId("2024-02-17"), "sunday"))).toBe(
183
+ "2024-02-11"
184
+ );
185
+ });
186
+ it("sunday: week of February 11th", () => {
187
+ expect(toDateId(startOfWeek(fromDateId("2024-02-11"), "sunday"))).toBe(
188
+ "2024-02-11"
189
+ );
190
+ });
191
+ it("monday: week of February 17th", () => {
192
+ expect(toDateId(startOfWeek(fromDateId("2024-02-17"), "monday"))).toBe(
193
+ "2024-02-12"
194
+ );
195
+ });
196
+ it("monday: week of February 11th", () => {
197
+ expect(toDateId(startOfWeek(fromDateId("2024-02-11"), "monday"))).toBe(
198
+ "2024-02-05"
199
+ );
200
+ });
201
+
202
+ it("matches date-fns", () => {
203
+ const baseDate = fromDateId("2020-01-01");
204
+ range(1, 1000).forEach((i) => {
205
+ const date = addDays(baseDate, i);
206
+ expect(startOfWeekDateFns(date, { weekStartsOn: 0 }).toISOString()).toBe(
207
+ startOfWeek(date, "sunday").toISOString()
208
+ );
209
+ expect(startOfWeekDateFns(date, { weekStartsOn: 1 }).toISOString()).toBe(
210
+ startOfWeek(date, "monday").toISOString()
211
+ );
212
+ });
213
+ });
214
+ });
215
+
216
+ describe("addMonths", () => {
217
+ const addMonthsCurried = (amount: number) => (date: Date) =>
218
+ addMonths(date, amount);
219
+ it("add 1 month", () => {
220
+ expect(
221
+ pipe(fromDateId("2024-01-01"), addMonthsCurried(1)).toISOString()
222
+ ).toBe(fromDateId("2024-02-01").toISOString());
223
+ });
224
+
225
+ it("add 10 months", () => {
226
+ expect(pipe(fromDateId("2024-01-01"), addMonthsCurried(10), toDateId)).toBe(
227
+ "2024-11-01"
228
+ );
229
+ });
230
+
231
+ it("matches date-fns", () => {
232
+ const baseDate = fromDateId("2020-01-01");
233
+ range(1, 100).forEach((i) => {
234
+ const date = addMonths(baseDate, i);
235
+ expect(addMonthsDateFns(baseDate, i).toISOString()).toBe(
236
+ date.toISOString()
237
+ );
238
+ });
239
+ });
240
+ });
241
+
242
+ describe("subMonths", () => {
243
+ const subMonthsCurried = (amount: number) => (date: Date) =>
244
+ subMonths(date, amount);
245
+ it("sub 1 month", () => {
246
+ expect(
247
+ pipe(fromDateId("2024-01-01"), subMonthsCurried(1)).toISOString()
248
+ ).toBe(fromDateId("2023-12-01").toISOString());
249
+ });
250
+
251
+ it("sub 10 months", () => {
252
+ expect(pipe(fromDateId("2024-01-01"), subMonthsCurried(10), toDateId)).toBe(
253
+ "2023-03-01"
254
+ );
255
+ });
256
+
257
+ it("matches date-fns", () => {
258
+ const baseDate = fromDateId("2020-01-01");
259
+ range(1, 100).forEach((i) => {
260
+ const date = subMonths(baseDate, i);
261
+ expect(subMonthsDateFns(baseDate, i).toISOString()).toBe(
262
+ date.toISOString()
263
+ );
264
+ });
265
+ });
266
+ });
267
+ describe("addDays", () => {
268
+ const addDaysCurried = (amount: number) => (date: Date) =>
269
+ addDays(date, amount);
270
+ it("add 1 day", () => {
271
+ expect(
272
+ pipe(fromDateId("2024-01-01"), addDaysCurried(1)).toISOString()
273
+ ).toBe(fromDateId("2024-01-02").toISOString());
274
+ });
275
+
276
+ it("add 10 days", () => {
277
+ expect(pipe(fromDateId("2024-01-01"), addDaysCurried(10), toDateId)).toBe(
278
+ "2024-01-11"
279
+ );
280
+ });
281
+
282
+ it("matches date-fns", () => {
283
+ const baseDate = fromDateId("2020-01-01");
284
+ range(1, 100).forEach((i) => {
285
+ const date = addDays(baseDate, i);
286
+ expect(addDaysDateFns(baseDate, i).toISOString()).toBe(
287
+ date.toISOString()
288
+ );
289
+ });
290
+ });
291
+ });
292
+
293
+ describe("subDays", () => {
294
+ const subDaysCurried = (amount: number) => (date: Date) =>
295
+ subDays(date, amount);
296
+
297
+ it("sub 1 day", () => {
298
+ expect(
299
+ pipe(fromDateId("2024-01-01"), subDaysCurried(1)).toISOString()
300
+ ).toBe(fromDateId("2023-12-31").toISOString());
301
+ });
302
+
303
+ it("sub 10 days", () => {
304
+ expect(pipe(fromDateId("2024-01-01"), subDaysCurried(10), toDateId)).toBe(
305
+ "2023-12-22"
306
+ );
307
+ });
308
+
309
+ it("matches date-fns", () => {
310
+ const baseDate = fromDateId("2020-01-01");
311
+ range(1, 100).forEach((i) => {
312
+ const date = subDays(baseDate, i);
313
+ expect(subDaysDateFns(baseDate, i).toISOString()).toBe(
314
+ date.toISOString()
315
+ );
316
+ });
317
+ });
318
+ });
319
+
320
+ describe("isWeekend", () => {
321
+ it("Friday", () => {
322
+ expect(pipe(fromDateId("2024-02-16"), isWeekend)).toBeFalse();
323
+ });
324
+ it("Saturday", () => {
325
+ expect(pipe(fromDateId("2024-02-17"), isWeekend)).toBeTrue();
326
+ });
327
+ it("Sunday", () => {
328
+ expect(pipe(fromDateId("2024-02-18"), isWeekend)).toBeTrue();
329
+ });
330
+ it("Monday", () => {
331
+ expect(pipe(fromDateId("2024-02-19"), isWeekend)).toBeFalse();
332
+ });
333
+ });
334
+
335
+ // This test suite was copied from date-fns source, with one change: our
336
+ // function returns `1` even if the dates aren't a full month apart
337
+ describe("differenceInMonths ", () => {
338
+ it("returns the number of full months between the given dates", () => {
339
+ const result = differenceInMonths(
340
+ new Date(2012, 6 /* Jul */, 2, 18, 0),
341
+ new Date(2011, 6 /* Jul */, 2, 6, 0)
342
+ );
343
+ expect(result).toBe(12);
344
+ });
345
+
346
+ it("returns a negative number if the time value of the first date is smaller", () => {
347
+ const result = differenceInMonths(
348
+ new Date(2011, 6 /* Jul */, 2, 6, 0),
349
+ new Date(2012, 6 /* Jul */, 2, 18, 0)
350
+ );
351
+ expect(result).toBe(-12);
352
+ });
353
+
354
+ describe("edge cases", () => {
355
+ it("it returns diff of 1 month between Feb 28 2021 and Jan 30 2021", () => {
356
+ const result = differenceInMonths(
357
+ new Date(2021, 1 /* Feb */, 28),
358
+ new Date(2021, 0 /* Jan */, 30)
359
+ );
360
+ expect(result).toBe(1);
361
+ });
362
+
363
+ it("it returns diff of 1 month between Feb 28 2021 and Jan 31 2021", () => {
364
+ const result = differenceInMonths(
365
+ new Date(2021, 1 /* Feb */, 28),
366
+ new Date(2021, 0 /* Jan */, 31)
367
+ );
368
+ expect(result).toBe(1);
369
+ });
370
+
371
+ it("it returns diff of 1 month between Nov, 30 2021 and Oct, 31 2021", () => {
372
+ const result = differenceInMonths(
373
+ new Date(2021, 10 /* Nov */, 30),
374
+ new Date(2021, 9 /* Oct */, 31)
375
+ );
376
+ expect(result).toBe(1);
377
+ });
378
+
379
+ it("it returns diff of 1 month between Oct, 31 2021 and Sep, 30 2021", () => {
380
+ const result = differenceInMonths(
381
+ new Date(2021, 9 /* Oct */, 31),
382
+ new Date(2021, 8 /* Sep */, 30)
383
+ );
384
+ expect(result).toBe(1);
385
+ });
386
+
387
+ it("it returns diff of 6 month between Oct, 31 2021 and Apr, 30 2021", () => {
388
+ const result = differenceInMonths(
389
+ new Date(2021, 9 /* Oct */, 31),
390
+ new Date(2021, 3 /* Apr */, 30)
391
+ );
392
+ expect(result).toBe(6);
393
+ });
394
+
395
+ it("it returns diff of -1 month between Sep, 30 2021 and Oct, 31 2021", () => {
396
+ const result = differenceInMonths(
397
+ new Date(2021, 8 /* Sep */, 30),
398
+ new Date(2021, 9 /* Oct */, 31)
399
+ );
400
+ expect(result).toBe(-1);
401
+ });
402
+
403
+ it("the days of months of the given dates are the same", () => {
404
+ const result = differenceInMonths(
405
+ new Date(2014, 8 /* Sep */, 6),
406
+ new Date(2014, 7 /* Aug */, 6)
407
+ );
408
+ expect(result).toBe(1);
409
+ });
410
+
411
+ it("the given dates are the same", () => {
412
+ const result = differenceInMonths(
413
+ new Date(2014, 8 /* Sep */, 5, 0, 0),
414
+ new Date(2014, 8 /* Sep */, 5, 0, 0)
415
+ );
416
+ expect(result).toBe(0);
417
+ });
418
+
419
+ it("does not return -0 when the given dates are the same", () => {
420
+ function isNegativeZero(x: number): boolean {
421
+ return x === 0 && 1 / x < 0;
422
+ }
423
+
424
+ const result = differenceInMonths(
425
+ new Date(2014, 8 /* Sep */, 5, 0, 0),
426
+ new Date(2014, 8 /* Sep */, 5, 0, 0)
427
+ );
428
+
429
+ const resultIsNegative = isNegativeZero(result);
430
+ expect(resultIsNegative).toBeFalse();
431
+ });
432
+ });
433
+
434
+ it("returns NaN if the first date is `Invalid Date`", () => {
435
+ const result = differenceInMonths(
436
+ new Date(NaN),
437
+ new Date(2017, 0 /* Jan */, 1)
438
+ );
439
+ expect(result).toBeNaN();
440
+ });
441
+
442
+ it("returns NaN if the second date is `Invalid Date`", () => {
443
+ const result = differenceInMonths(
444
+ new Date(2017, 0 /* Jan */, 1),
445
+ new Date(NaN)
446
+ );
447
+ expect(result).toBeNaN();
448
+ });
449
+
450
+ it("returns NaN if the both dates are `Invalid Date`", () => {
451
+ const result = differenceInMonths(new Date(NaN), new Date(NaN));
452
+ expect(result).toBeNaN();
453
+ });
454
+
455
+ describe("edge cases", () => {
456
+ it("returns the number of full months between the given dates - end of Feb", () => {
457
+ expect(
458
+ differenceInMonths(
459
+ new Date(2012, 1 /* Feb */, 29, 9, 0, 0),
460
+ new Date(2012, 1 /* Feb */, 29, 10, 0, 0)
461
+ )
462
+ ).toBe(0);
463
+
464
+ expect(
465
+ differenceInMonths(
466
+ new Date(2012, 1 /* Feb */, 28, 9, 0, 0),
467
+ new Date(2012, 1 /* Feb */, 29, 10, 0, 0)
468
+ )
469
+ ).toBe(0);
470
+ expect(
471
+ differenceInMonths(
472
+ new Date(2012, 1 /* Feb */, 27, 9, 0, 0),
473
+ new Date(2012, 1 /* Feb */, 27, 10, 0, 0)
474
+ )
475
+ ).toBe(0);
476
+ expect(
477
+ differenceInMonths(
478
+ new Date(2012, 1 /* Feb */, 28, 9, 0, 0),
479
+ new Date(2012, 1 /* Feb */, 28, 10, 0, 0)
480
+ )
481
+ ).toBe(0);
482
+ });
483
+
484
+ expect(
485
+ differenceInMonths(
486
+ new Date(2021, 1 /* Feb */, 28, 7, 23, 7),
487
+ new Date(2021, 1 /* Feb */, 28, 7, 38, 18)
488
+ )
489
+ ).toBe(0);
490
+ });
491
+ });
492
+
493
+ describe("getWeeksInMonth", () => {
494
+ const getWeeksInMonth_sunday = (date: Date) =>
495
+ getWeeksInMonth(date, "sunday");
496
+
497
+ const getWeeksInMonth_monday = (date: Date) =>
498
+ getWeeksInMonth(date, "monday");
499
+
500
+ it("sunday: Month with 5 weeks", () => {
501
+ expect(pipe(fromDateId("2024-01-01"), getWeeksInMonth_sunday)).toBe(5);
502
+ expect(pipe(fromDateId("2024-02-13"), getWeeksInMonth_sunday)).toBe(5);
503
+ expect(pipe(fromDateId("2024-04-01"), getWeeksInMonth_sunday)).toBe(5);
504
+ expect(pipe(fromDateId("2024-05-31"), getWeeksInMonth_sunday)).toBe(5);
505
+ });
506
+
507
+ it("sunday: Month with 6 weeks", () => {
508
+ expect(pipe(fromDateId("2024-03-01"), getWeeksInMonth_sunday)).toBe(6);
509
+ expect(pipe(fromDateId("2024-06-30"), getWeeksInMonth_sunday)).toBe(6);
510
+ });
511
+
512
+ it("monday: Month with 5 weeks", () => {
513
+ expect(pipe(fromDateId("2024-01-01"), getWeeksInMonth_monday)).toBe(5);
514
+ expect(pipe(fromDateId("2024-02-13"), getWeeksInMonth_monday)).toBe(5);
515
+ expect(pipe(fromDateId("2024-03-01"), getWeeksInMonth_monday)).toBe(5);
516
+ expect(pipe(fromDateId("2024-04-01"), getWeeksInMonth_monday)).toBe(5);
517
+ expect(pipe(fromDateId("2024-05-31"), getWeeksInMonth_monday)).toBe(5);
518
+ expect(pipe(fromDateId("2024-06-30"), getWeeksInMonth_monday)).toBe(5);
519
+ });
520
+
521
+ it("matches date-fns", () => {
522
+ const baseDate = fromDateId("2020-01-01");
523
+ range(1, 500).forEach((i) => {
524
+ const date = addMonths(baseDate, i);
525
+ const countMonday = getWeeksInMonthDateFns(date, { weekStartsOn: 1 });
526
+ const countSunday = getWeeksInMonthDateFns(date, { weekStartsOn: 0 });
527
+
528
+ expect(getWeeksInMonth(date, "monday")).toBe(countMonday);
529
+ expect(getWeeksInMonth(date, "sunday")).toBe(countSunday);
530
+ });
531
+ });
532
+ });
533
+
534
+ describe("getWeekOfMonth", () => {
535
+ const getWeekOfMonth_sunday = (date: Date) => getWeekOfMonth(date, "sunday");
536
+ const getWeekOfMonth_monday = (date: Date) => getWeekOfMonth(date, "monday");
537
+
538
+ it("sunday: June", () => {
539
+ expect(pipe(fromDateId("2024-06-01"), getWeekOfMonth_sunday)).toBe(1);
540
+ expect(pipe(fromDateId("2024-06-02"), getWeekOfMonth_sunday)).toBe(2);
541
+ expect(pipe(fromDateId("2024-06-03"), getWeekOfMonth_monday)).toBe(2);
542
+ expect(pipe(fromDateId("2024-06-12"), getWeekOfMonth_sunday)).toBe(3);
543
+ expect(pipe(fromDateId("2024-06-22"), getWeekOfMonth_sunday)).toBe(4);
544
+ expect(pipe(fromDateId("2024-06-28"), getWeekOfMonth_sunday)).toBe(5);
545
+ expect(pipe(fromDateId("2024-06-30"), getWeekOfMonth_sunday)).toBe(6);
546
+ });
547
+ it("monday: June", () => {
548
+ expect(pipe(fromDateId("2024-06-01"), getWeekOfMonth_monday)).toBe(1);
549
+ expect(pipe(fromDateId("2024-06-02"), getWeekOfMonth_monday)).toBe(1);
550
+ expect(pipe(fromDateId("2024-06-03"), getWeekOfMonth_monday)).toBe(2);
551
+ expect(pipe(fromDateId("2024-06-12"), getWeekOfMonth_monday)).toBe(3);
552
+ expect(pipe(fromDateId("2024-06-22"), getWeekOfMonth_monday)).toBe(4);
553
+ expect(pipe(fromDateId("2024-06-28"), getWeekOfMonth_monday)).toBe(5);
554
+ expect(pipe(fromDateId("2024-06-30"), getWeekOfMonth_monday)).toBe(5);
555
+ });
556
+ it("matches date-fns", () => {
557
+ const baseDate = fromDateId("2024-06-01");
558
+ range(1, 500).forEach((i) => {
559
+ const date = addDays(baseDate, i);
560
+ const countMonday = getWeekOfMonthDateFns(date, { weekStartsOn: 1 });
561
+ const countSunday = getWeekOfMonthDateFns(date, { weekStartsOn: 0 });
562
+
563
+ expect(getWeekOfMonth(date, "monday")).toBe(countMonday);
564
+ expect(getWeekOfMonth(date, "sunday")).toBe(countSunday);
565
+ });
566
+ });
567
+ });