@bash-app/bash-common 30.57.0 → 30.58.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 (43) hide show
  1. package/dist/extendedSchemas.d.ts +44 -0
  2. package/dist/extendedSchemas.d.ts.map +1 -1
  3. package/dist/extendedSchemas.js +6 -0
  4. package/dist/extendedSchemas.js.map +1 -1
  5. package/dist/utils/dateTimeUtils.d.ts +1 -17
  6. package/dist/utils/dateTimeUtils.d.ts.map +1 -1
  7. package/dist/utils/dateTimeUtils.js +1 -114
  8. package/dist/utils/dateTimeUtils.js.map +1 -1
  9. package/dist/utils/luxonUtils.d.ts +17 -6
  10. package/dist/utils/luxonUtils.d.ts.map +1 -1
  11. package/dist/utils/luxonUtils.js +31 -3
  12. package/dist/utils/luxonUtils.js.map +1 -1
  13. package/dist/utils/recurrenceUtils.d.ts +1 -1
  14. package/dist/utils/recurrenceUtils.d.ts.map +1 -1
  15. package/dist/utils/recurrenceUtils.js +24 -49
  16. package/dist/utils/recurrenceUtils.js.map +1 -1
  17. package/dist/utils/service/apiServiceBookingApiUtils.d.ts +14 -2
  18. package/dist/utils/service/apiServiceBookingApiUtils.d.ts.map +1 -1
  19. package/dist/utils/service/apiServiceBookingApiUtils.js +36 -2
  20. package/dist/utils/service/apiServiceBookingApiUtils.js.map +1 -1
  21. package/dist/utils/service/frontendServiceBookingUtils.d.ts +10 -3
  22. package/dist/utils/service/frontendServiceBookingUtils.d.ts.map +1 -1
  23. package/dist/utils/service/frontendServiceBookingUtils.js +86 -40
  24. package/dist/utils/service/frontendServiceBookingUtils.js.map +1 -1
  25. package/dist/utils/service/serviceBookingTypes.d.ts +4 -2
  26. package/dist/utils/service/serviceBookingTypes.d.ts.map +1 -1
  27. package/dist/utils/ticketListUtils.d.ts.map +1 -1
  28. package/dist/utils/ticketListUtils.js +10 -13
  29. package/dist/utils/ticketListUtils.js.map +1 -1
  30. package/dist/utils/typeUtils.d.ts +5 -0
  31. package/dist/utils/typeUtils.d.ts.map +1 -1
  32. package/dist/utils/typeUtils.js.map +1 -1
  33. package/package.json +1 -1
  34. package/prisma/schema.prisma +31 -41
  35. package/src/extendedSchemas.ts +9 -0
  36. package/src/utils/dateTimeUtils.ts +7 -190
  37. package/src/utils/luxonUtils.ts +56 -10
  38. package/src/utils/recurrenceUtils.ts +97 -77
  39. package/src/utils/service/apiServiceBookingApiUtils.ts +64 -7
  40. package/src/utils/service/frontendServiceBookingUtils.ts +120 -49
  41. package/src/utils/service/serviceBookingTypes.ts +30 -2
  42. package/src/utils/ticketListUtils.ts +40 -27
  43. package/src/utils/typeUtils.ts +15 -8
@@ -4,12 +4,6 @@ import { DateTimeArgType } from "../definitions";
4
4
 
5
5
  const PARSE_TIME_REG = /^(\d{1,2}):(\d{2}) ?([APM]{0,2})$/i;
6
6
 
7
- export const DATETIME_FORMAT_STANDARD = "MMM d, yyyy - h:mm a";
8
- export const DATETIME_FORMAT_ISO_LIKE = "yyyy-MM-dd HH:mm";
9
- export const DATE_FORMAT_STANDARD = "MM/dd/yyyy";
10
- export const DATE_FORMAT_ISO = "yyyy-MM-dd";
11
- export const TIME_FORMAT_AM_PM = "h:mm a";
12
-
13
7
  export interface ITime {
14
8
  hours: number;
15
9
  minutes: number;
@@ -20,84 +14,6 @@ export function getLocalTimezoneName(): string {
20
14
  return DateTime.local().zoneName;
21
15
  }
22
16
 
23
- export function formatDateRangeBasic(
24
- startDateTimeArg: Date | null,
25
- endDateTimeArg: Date | null
26
- ): string {
27
- const userTimezone = getLocalTimezoneName();
28
- const startDateTime = DateTime.fromJSDate(startDateTimeArg || new Date()).setZone(userTimezone);
29
- const endDateTime = DateTime.fromJSDate(endDateTimeArg || new Date()).setZone(userTimezone);
30
-
31
- if (startDateTime.hasSame(endDateTime, "day")) {
32
- return `${startDateTime.toFormat(
33
- DATETIME_FORMAT_STANDARD
34
- )} to ${endDateTime.toFormat(TIME_FORMAT_AM_PM)}`;
35
- }
36
-
37
- return `${startDateTime.toFormat(
38
- DATETIME_FORMAT_STANDARD
39
- )} to ${endDateTime.toFormat(DATETIME_FORMAT_STANDARD)}`;
40
- }
41
-
42
- export function formatDateRangeBasicWithTimezone(
43
- startDateTimeArg: Date | null,
44
- endDateTimeArg: Date | null,
45
- timezone?: string
46
- ): string {
47
- const targetTimezone = timezone || getLocalTimezoneName();
48
- const startDateTime = DateTime.fromJSDate(startDateTimeArg || new Date()).setZone(targetTimezone);
49
- const endDateTime = DateTime.fromJSDate(endDateTimeArg || new Date()).setZone(targetTimezone);
50
-
51
- if (startDateTime.hasSame(endDateTime, "day")) {
52
- return `${startDateTime.toFormat(
53
- DATETIME_FORMAT_STANDARD
54
- )} to ${endDateTime.toFormat(TIME_FORMAT_AM_PM)}`;
55
- }
56
-
57
- return `${startDateTime.toFormat(
58
- DATETIME_FORMAT_STANDARD
59
- )} to ${endDateTime.toFormat(DATETIME_FORMAT_STANDARD)}`;
60
- }
61
-
62
- export function formatDateRange(
63
- startDateTimeArg: Date | null,
64
- endDateTimeArg: Date | null
65
- ): string {
66
- const userTimezone = getLocalTimezoneName();
67
- const startDateTime = ensureDateTimeIsLocalDateTime(startDateTimeArg).setZone(userTimezone);
68
- const endDateTime = ensureDateTimeIsLocalDateTime(endDateTimeArg).setZone(userTimezone);
69
-
70
- if (startDateTime.hasSame(endDateTime, "day")) {
71
- return `${startDateTime.toFormat(
72
- DATETIME_FORMAT_STANDARD
73
- )} to ${endDateTime.toFormat(TIME_FORMAT_AM_PM)}`;
74
- }
75
-
76
- return `${startDateTime.toFormat(
77
- DATETIME_FORMAT_STANDARD
78
- )} to ${endDateTime.toFormat(DATETIME_FORMAT_STANDARD)}`;
79
- }
80
-
81
- export function formatDateRangeWithTimezone(
82
- startDateTimeArg: Date | null,
83
- endDateTimeArg: Date | null,
84
- timezone?: string
85
- ): string {
86
- const targetTimezone = timezone || getLocalTimezoneName();
87
- const startDateTime = ensureDateTimeIsLocalDateTime(startDateTimeArg).setZone(targetTimezone);
88
- const endDateTime = ensureDateTimeIsLocalDateTime(endDateTimeArg).setZone(targetTimezone);
89
-
90
- if (startDateTime.hasSame(endDateTime, "day")) {
91
- return `${startDateTime.toFormat(
92
- DATETIME_FORMAT_STANDARD
93
- )} to ${endDateTime.toFormat(TIME_FORMAT_AM_PM)}`;
94
- }
95
-
96
- return `${startDateTime.toFormat(
97
- DATETIME_FORMAT_STANDARD
98
- )} to ${endDateTime.toFormat(DATETIME_FORMAT_STANDARD)}`;
99
- }
100
-
101
17
  export function ensureIsDateTime(
102
18
  possiblyADate: DateTimeArgType
103
19
  ): Date | undefined {
@@ -134,23 +50,17 @@ export function normalizeDates(
134
50
  .filter((date): date is Date => !!date); // Filter out invalid dates
135
51
  }
136
52
 
137
- export function formatDateTimeToISODateTimeString(
138
- date: DateTimeArgType
139
- ): string | undefined {
140
- if (!date) {
141
- return undefined;
142
- }
143
- date = new Date(date);
144
- return date.toISOString();
145
- }
146
-
147
53
  export function dateWithinDateRange(
148
54
  date: DateTimeArgType,
149
55
  dateRange: DateValueType | undefined
150
56
  ): boolean {
151
- const startDate = DateTime.fromJSDate(dateRange?.startDate || new Date()).startOf("day");
152
- const endDate = DateTime.fromJSDate(dateRange?.endDate || new Date()).endOf("day");
153
- const checkDate = DateTime.fromJSDate(new Date(date || ''));
57
+ const startDate = DateTime.fromJSDate(
58
+ dateRange?.startDate || new Date()
59
+ ).startOf("day");
60
+ const endDate = DateTime.fromJSDate(dateRange?.endDate || new Date()).endOf(
61
+ "day"
62
+ );
63
+ const checkDate = DateTime.fromJSDate(new Date(date || ""));
154
64
 
155
65
  return checkDate >= startDate && checkDate < endDate;
156
66
  }
@@ -221,99 +131,6 @@ export function compareDateTime(
221
131
  }
222
132
  }
223
133
 
224
- export function setDateButPreserveTime(
225
- dateArg: DateType,
226
- dateWithTheTimeYouWantToKeep: DateType | undefined
227
- ): Date {
228
- if (!dateArg || !dateWithTheTimeYouWantToKeep) {
229
- console.error("Invalid arguments:", {
230
- dateArg,
231
- dateWithTheTimeYouWantToKeep,
232
- });
233
- throw new Error(
234
- "Both dateArg and dateWithTheTimeYouWantToKeep are required."
235
- );
236
- }
237
-
238
- // Get local timezone
239
- const localTimeZone = getLocalTimezoneName();
240
-
241
- // Extract date and time components using Luxon
242
- const dateOnly = DateTime.fromJSDate(new Date(dateArg)).setZone(localTimeZone);
243
- const timeOnly = DateTime.fromJSDate(new Date(dateWithTheTimeYouWantToKeep)).setZone(localTimeZone);
244
-
245
- // Combine date from first argument with time from second argument
246
- const combinedDateTime = dateOnly.set({
247
- hour: timeOnly.hour,
248
- minute: timeOnly.minute,
249
- second: 0,
250
- millisecond: 0
251
- });
252
-
253
- console.log("Combining date and time:", {
254
- dateOnly: dateOnly.toISO(),
255
- timeOnly: timeOnly.toFormat("HH:mm"),
256
- combinedDateTime: combinedDateTime.toISO(),
257
- localTimeZone,
258
- });
259
-
260
- const result = combinedDateTime.toJSDate();
261
- if (isNaN(result.getTime())) {
262
- console.error("Invalid combined datetime:", combinedDateTime.toISO());
263
- throw new Error("Invalid date or time format.");
264
- }
265
-
266
- console.log("Final combined DateTime (UTC):", result);
267
- return result;
268
- }
269
-
270
- export function setTimeOnDate(
271
- date: DateType | Date | undefined,
272
- parsedTime: ITime | null
273
- ): Date {
274
- const dateTime = DateTime.fromJSDate(date ? new Date(date) : new Date());
275
-
276
- if (parsedTime) {
277
- const updatedDateTime = dateTime.set({
278
- hour: parsedTime.hours,
279
- minute: parsedTime.minutes,
280
- second: 0,
281
- millisecond: 0
282
- });
283
- return setDateButPreserveTime(dateTime.toJSDate(), updatedDateTime.toJSDate());
284
- }
285
- return dateTime.toJSDate();
286
- }
287
-
288
- export function ensureDateTimeIsLocalDateTime(
289
- dateArg: DateType | DateTime | undefined
290
- ): DateTime {
291
- if (!dateArg) {
292
- return DateTime.local();
293
- }
294
-
295
- if (dateArg instanceof DateTime) {
296
- return dateArg.setZone(getLocalTimezoneName());
297
- }
298
-
299
- const dt = DateTime.fromJSDate(new Date(dateArg));
300
- return dt.setZone(getLocalTimezoneName());
301
- }
302
-
303
- export function formatDateTimeToTimeString(
304
- date: Date | string | undefined | null
305
- ): string {
306
- const dt = DateTime.fromJSDate(new Date(date ?? Date.now()));
307
- return dt.toFormat("h:mm a");
308
- }
309
-
310
- export function formatDateTimeToTimeString24hr(
311
- date: Date | string | undefined | null
312
- ): string {
313
- const dt = DateTime.fromJSDate(new Date(date ?? Date.now()));
314
- return dt.toFormat("H:mm");
315
- }
316
-
317
134
  export function parseTimeString(timeStr: string): ITime | null {
318
135
  const match = timeStr.match(PARSE_TIME_REG);
319
136
 
@@ -8,11 +8,11 @@ import {
8
8
  } from "./generalDateTimeUtils";
9
9
  import { roundToNearestDivisor } from "./mathUtils";
10
10
 
11
- const PARSE_TIME_REG = /^(\d{1,2}):(\d{2}) ?([APM]{0,2})$/i;
12
-
13
11
  // export const LUXON_DATETIME_FORMAT_STANDARD = "MM/dd/yyyy - hh:mm a";
14
12
  export const LUXON_DATETIME_FORMAT_STANDARD = "D t";
13
+ export const LUXON_DATETIME_FORMAT_ISO = "D t"; //"D t";
15
14
  export const LUXON_DATETIME_FORMAT_ISO_LIKE = "D t"; //"D t";
15
+ export const LUXON_DATETIME_FORMAT_STANDARD_EXTENDED = "cccc D T";
16
16
  // export const LUXON_DATE_FORMAT_STANDARD = "yyyy/MM/dd";
17
17
  // export const LUXON_DATE_FORMAT_ISO = "yyyy/MM/dd";
18
18
  export const LUXON_DATETIME_FORMAT_DATE = "D"; //"D t";
@@ -20,6 +20,19 @@ export const LUXON_TIME_FORMAT_AM_PM = "h:mm a";
20
20
 
21
21
  export const MINUTES_PER_DAY = 1440;
22
22
 
23
+ export const INVALID_DATETIME_STR = "Invalid date";
24
+ export const INVALID_DATETIME_RANGE_STR = "Invalid date range";
25
+
26
+ export interface LuxonDateRange {
27
+ start: DateTime;
28
+ end: DateTime;
29
+ }
30
+
31
+ export interface LuxonDateRangeN {
32
+ start?: DateTime | undefined | null;
33
+ end?: DateTime | undefined | null;
34
+ }
35
+
23
36
  export function dayOfWeekGetIdx(dayOfWeek: DayOfWeek | DayOfWeekIdx) {
24
37
  if (typeof dayOfWeek === "number") {
25
38
  return dayOfWeek as DayOfWeekIdx;
@@ -30,6 +43,16 @@ export function dayOfWeekGetIdx(dayOfWeek: DayOfWeek | DayOfWeekIdx) {
30
43
  }
31
44
  }
32
45
 
46
+ export function dayOfWeekFromIdx(dayOfWeek: DayOfWeek | DayOfWeekIdx) {
47
+ if (typeof dayOfWeek === "number") {
48
+ return dayOfWeekIdxToDayOfWeek[dayOfWeek as DayOfWeekIdx];
49
+ } else if (typeof dayOfWeek === "string") {
50
+ return dayOfWeek as DayOfWeek;
51
+ } else {
52
+ throw new Error(`dayOfWeekToIdx: unhandled case`);
53
+ }
54
+ }
55
+
33
56
  export function dateTimeFromDayTime(
34
57
  dayOfWeek: DayOfWeek | DayOfWeekIdx,
35
58
  hour: number = 0,
@@ -192,12 +215,25 @@ export function dateRangeGetDateTimeTIme(dateRange: LuxonDateRange) {
192
215
  };
193
216
  }
194
217
 
195
- export function dateTimeFormat(dateTime?: DateTime | null) {
218
+ export function dateTimeFormat(dateTime?: DateTime | undefined | null) {
196
219
  return dateTime?.toFormat(LUXON_DATETIME_FORMAT_STANDARD) ?? "";
197
220
  }
198
221
 
199
- export function dateTimeFormatLong(dateTime?: DateTime | null) {
200
- return `${dateTime?.weekdayLong} ${dateTimeFormatWeek(dateTime)}`;
222
+ export function dateTimeFormatExt(
223
+ dateTime?: DateTime | undefined | null
224
+ ): string {
225
+ return dateTime
226
+ ? `${dateTime.toFormat(LUXON_DATETIME_FORMAT_STANDARD_EXTENDED)}`
227
+ : "";
228
+ }
229
+
230
+ export function dateTimeFormatISO(
231
+ dateTime?: DateTime | undefined | null
232
+ ): string | null {
233
+ if (!dateTime) {
234
+ return null;
235
+ }
236
+ return dateTime.toISO();
201
237
  }
202
238
 
203
239
  export function dateTimeFormatWeek(dateTime?: DateTime | null) {
@@ -296,6 +332,21 @@ export function dateTimeFormatDateRange(
296
332
  )}`;
297
333
  }
298
334
 
335
+ export function dateTimeFormatDateRangeExt(
336
+ startDateTimeArg: DateTime | null,
337
+ endDateTimeArg: DateTime | null
338
+ ): string {
339
+ if (startDateTimeArg?.day === endDateTimeArg?.day) {
340
+ return `${dateTimeFormatExt(startDateTimeArg)} to ${dateTimeFormatTime(
341
+ endDateTimeArg
342
+ )}`;
343
+ }
344
+
345
+ return `${dateTimeFormatExt(startDateTimeArg)} to ${dateTimeFormat(
346
+ endDateTimeArg
347
+ )}`;
348
+ }
349
+
299
350
  export function dateTimeFormatDateRangeDate(
300
351
  startDateTimeArg: DateTime | null,
301
352
  endDateTimeArg: DateTime | null
@@ -333,11 +384,6 @@ export function dateTimeFormatDateRangeList(
333
384
  };
334
385
  }
335
386
 
336
- export interface LuxonDateRange {
337
- start: DateTime;
338
- end: DateTime;
339
- }
340
-
341
387
  export type LuxonDayOfWeekHours = {
342
388
  [key in DayOfWeekIdx]: LuxonDateRange[];
343
389
  };
@@ -1,27 +1,54 @@
1
1
  import { DayOfWeek, Recurrence, RecurringFrequency } from "@prisma/client";
2
2
  import { DateTime, WeekdayNumbers } from "luxon";
3
3
  import { DateTimeArgType } from "../definitions";
4
- import { compareDateTime, DATETIME_FORMAT_ISO_LIKE } from "./dateTimeUtils";
4
+ import {
5
+ dateTimeFromDate,
6
+ dateTimeSetTime,
7
+ dayOfWeekGetIdx,
8
+ LUXON_DATETIME_FORMAT_ISO_LIKE,
9
+ } from "./luxonUtils";
10
+ import { compareDateTime } from "./dateTimeUtils";
11
+ import { dayOfWeekToIdx } from "./generalDateTimeUtils";
5
12
 
6
- export function getRecurringBashEventPossibleDateTimes(startDateTime: DateTimeArgType,
7
- recurrence: Recurrence | undefined | null): Date[] {
8
- return getRecurringBashEventPossibleDatesTimesInternal(startDateTime, recurrence, true) as Date[];
13
+ export function getRecurringBashEventPossibleDateTimes(
14
+ startDateTime: DateTimeArgType,
15
+ recurrence: Recurrence | undefined | null
16
+ ): Date[] {
17
+ return getRecurringBashEventPossibleDatesTimesInternal(
18
+ startDateTime,
19
+ recurrence,
20
+ true
21
+ ) as Date[];
9
22
  }
10
23
 
11
- export function getRecurringBashEventPossibleDayjsTimes(startDateTime: DateTimeArgType,
12
- recurrence: Recurrence | undefined | null): DateTime[] {
13
- return getRecurringBashEventPossibleDatesTimesInternal(startDateTime, recurrence, false) as DateTime[];
24
+ export function getRecurringBashEventPossibleLuxonTimes(
25
+ startDateTime: DateTimeArgType,
26
+ recurrence: Recurrence | undefined | null
27
+ ): DateTime[] {
28
+ return getRecurringBashEventPossibleDatesTimesInternal(
29
+ startDateTime,
30
+ recurrence,
31
+ false
32
+ ) as DateTime[];
14
33
  }
15
34
 
16
- function getRecurringBashEventPossibleDatesTimesInternal(startDateTime: DateTimeArgType,
17
- recurrence: Recurrence | undefined | null,
18
- toDate: boolean): (DateTime | Date)[] {
19
- if (!recurrence || !recurrence.frequency || recurrence.frequency === RecurringFrequency.Never) {
35
+ function getRecurringBashEventPossibleDatesTimesInternal(
36
+ startDateTime: DateTimeArgType,
37
+ recurrence: Recurrence | undefined | null,
38
+ toDate: boolean
39
+ ): (DateTime | Date)[] {
40
+ if (
41
+ !recurrence ||
42
+ !recurrence.frequency ||
43
+ recurrence.frequency === RecurringFrequency.Never
44
+ ) {
20
45
  return [];
21
46
  }
22
47
 
23
48
  let recurrenceDates: DateTime[] = [];
24
- const beginningDate = findEarliestPossibleBashEventDate(startDateTime) as DateTime; // Don't allow dates before the current date
49
+ const beginningDate = findEarliestPossibleBashEventDate(
50
+ startDateTime
51
+ ) as DateTime; // Don't allow dates before the current date
25
52
 
26
53
  switch (recurrence.frequency) {
27
54
  case RecurringFrequency.Weekly:
@@ -30,17 +57,22 @@ function getRecurringBashEventPossibleDatesTimesInternal(startDateTime: DateTime
30
57
  default:
31
58
  console.error(`Only weekly frequency is currently supported`);
32
59
  }
33
- return recurrenceDates.map((date: DateTime): string => date.toFormat(DATETIME_FORMAT_ISO_LIKE))
34
- .sort()
35
- .map((dateStr: string): DateTime | Date => {
36
- const luxonDate = DateTime.fromFormat(dateStr, DATETIME_FORMAT_ISO_LIKE);
37
- if (toDate) {
38
- return luxonDate.toJSDate();
39
- }
40
- else {
41
- return luxonDate;
42
- }
43
- });
60
+ return recurrenceDates
61
+ .map((date: DateTime): string =>
62
+ date.toFormat(LUXON_DATETIME_FORMAT_ISO_LIKE)
63
+ )
64
+ .sort()
65
+ .map((dateStr: string): DateTime | Date => {
66
+ const luxonDate = DateTime.fromFormat(
67
+ dateStr,
68
+ LUXON_DATETIME_FORMAT_ISO_LIKE
69
+ );
70
+ if (toDate) {
71
+ return luxonDate.toJSDate();
72
+ } else {
73
+ return luxonDate;
74
+ }
75
+ });
44
76
  }
45
77
 
46
78
  /**
@@ -48,15 +80,20 @@ function getRecurringBashEventPossibleDatesTimesInternal(startDateTime: DateTime
48
80
  * @param beginningDateTime The beginning DateTime of the event, adjusted to be no earlier than now.
49
81
  * @param recurrence
50
82
  */
51
- function getWeeklyRecurringDates(beginningDateTime: DateTime, recurrence: Recurrence): DateTime[] {
83
+ function getWeeklyRecurringDates(
84
+ beginningDateTime: DateTime,
85
+ recurrence: Recurrence
86
+ ): DateTime[] {
52
87
  if (recurrence.frequency !== RecurringFrequency.Weekly) {
53
- throw new Error(`Cannot do a weekly recurrence if the frequency isn't weekly.`);
88
+ throw new Error(
89
+ `Cannot do a weekly recurrence if the frequency isn't weekly.`
90
+ );
54
91
  }
55
92
 
56
93
  const interval = recurrence.interval ?? 1;
57
- const recurrenceEnds = DateTime.fromJSDate(new Date(recurrence.ends || '')).endOf('day'); // Get the end of the day to not miss the last day
58
- const numberOfDays = recurrenceEnds.diff(beginningDateTime, 'days').days;
59
- const numberOfWeeks = Math.ceil((numberOfDays / 7) / interval); // Get the number of days and then round up so that we include the ending date
94
+ const recurrenceEnds = dateTimeFromDate(recurrence.ends).endOf("day"); // Get the end of the day to not miss the last day
95
+ const numberOfDays = recurrenceEnds.diff(beginningDateTime, "days").days;
96
+ const numberOfWeeks = Math.ceil(numberOfDays / 7 / interval); // Get the number of days and then round up so that we include the ending date
60
97
 
61
98
  const recurrenceDates: DateTime[] = [];
62
99
  let theNextWeekOfRecurrences = beginningDateTime;
@@ -65,13 +102,15 @@ function getWeeklyRecurringDates(beginningDateTime: DateTime, recurrence: Recurr
65
102
  for (let i = 0; i < numberOfWeeks; i++) {
66
103
  let weekday: DateTime | null = null;
67
104
  for (const dayOfWeekEnum of recurrence.repeatOnDays) {
68
- const dayOfWeekNum = dayOfWeekEnumToDayNumber(dayOfWeekEnum);
69
- weekday = theNextWeekOfRecurrences.set({ weekday: dayOfWeekNum as WeekdayNumbers });
105
+ const dayOfWeekNum = dayOfWeekGetIdx(dayOfWeekEnum);
106
+ weekday = theNextWeekOfRecurrences.set({
107
+ weekday: dayOfWeekNum as WeekdayNumbers,
108
+ });
70
109
  if (weekday > recurrenceEnds || weekday < beginningDateTime) {
71
110
  continue; // Continue because repeatOnDays isn't sorted by the day of the week
72
111
  }
73
112
  // Set the time on the date so that it matches the time when the event starts
74
- weekday = copyTimeToDate(beginningDateTime, weekday);
113
+ weekday = dateTimeSetTime(weekday, beginningDateTime);
75
114
  recurrenceDates.push(weekday);
76
115
  }
77
116
  if (weekday) {
@@ -81,54 +120,28 @@ function getWeeklyRecurringDates(beginningDateTime: DateTime, recurrence: Recurr
81
120
  return recurrenceDates;
82
121
  }
83
122
 
84
- function copyTimeToDate(dateWithTimeToCopy: DateTime, dateWhoseTimeToChange: DateTime): DateTime {
85
- if (dateWithTimeToCopy.second !== 0) {
86
- console.warn(`dateWithTimeToCopy has non-zero seconds: ${dateWithTimeToCopy.toString()} \nFixing...`);
87
- dateWithTimeToCopy = dateWithTimeToCopy.set({second: 0});
88
- }
89
- return dateWhoseTimeToChange.set({
90
- hour: dateWithTimeToCopy.hour,
91
- minute: dateWithTimeToCopy.minute,
92
- second: 0
93
- });
94
- }
95
-
96
- function dayOfWeekEnumToDayNumber(dayEnum: DayOfWeek): number {
97
- switch (dayEnum) {
98
- case DayOfWeek.Sunday:
99
- return 7; // Luxon uses 1-7 where 7 is Sunday
100
- case DayOfWeek.Monday:
101
- return 1;
102
- case DayOfWeek.Tuesday:
103
- return 2;
104
- case DayOfWeek.Wednesday:
105
- return 3;
106
- case DayOfWeek.Thursday:
107
- return 4;
108
- case DayOfWeek.Friday:
109
- return 5;
110
- case DayOfWeek.Saturday:
111
- return 6;
112
- default:
113
- throw new Error(`How did this happen? Invalid DayOfWeek: ${dayEnum}`); // Shouldn't happen
114
- }
115
- }
116
-
117
123
  /**
118
124
  * Get the next week determined by the interval by going to the end of the week interval and adding one day
119
125
  * @param date
120
126
  * @param interval
121
127
  */
122
- function getBeginningOfWeekInterval(date: DateTime, interval: number): DateTime {
128
+ function getBeginningOfWeekInterval(
129
+ date: DateTime,
130
+ interval: number
131
+ ): DateTime {
123
132
  if (!interval) {
124
133
  interval = 1; // Avoid 0
125
134
  }
126
135
  // An interval of 2 would be (2 - 1) * 7 + 1 = 8 days to add to skip a week and go into the next week
127
136
  const numberOfDaysToAdd = interval > 1 ? (interval - 1) * 7 + 1 : 1;
128
- return date.endOf('week').plus({ days: numberOfDaysToAdd });
137
+ return date.endOf("week").plus({ days: numberOfDaysToAdd });
129
138
  }
130
139
 
131
- export function freqToGrammarString(freq: RecurringFrequency, interval: number | undefined, toLowerCase: boolean = false): string {
140
+ export function freqToGrammarString(
141
+ freq: RecurringFrequency,
142
+ interval: number | undefined,
143
+ toLowerCase: boolean = false
144
+ ): string {
132
145
  if (!interval) {
133
146
  return freq;
134
147
  }
@@ -136,37 +149,44 @@ export function freqToGrammarString(freq: RecurringFrequency, interval: number |
136
149
  let result: string = freq;
137
150
  switch (freq) {
138
151
  case RecurringFrequency.Daily:
139
- result = isPlural ? 'Days' : 'Day';
152
+ result = isPlural ? "Days" : "Day";
140
153
  break;
141
154
  case RecurringFrequency.Weekly:
142
- result = isPlural ? 'Weeks' : 'Week';
155
+ result = isPlural ? "Weeks" : "Week";
143
156
  break;
144
157
  case RecurringFrequency.Monthly:
145
- result = isPlural ? 'Months' : 'Month';
158
+ result = isPlural ? "Months" : "Month";
146
159
  break;
147
160
  case RecurringFrequency.Yearly:
148
- result = isPlural ? 'Years' : 'Year';
161
+ result = isPlural ? "Years" : "Year";
149
162
  break;
150
163
  }
151
164
  return toLowerCase ? result.toLowerCase() : result;
152
165
  }
153
166
 
154
- export function findEarliestPossibleBashEventDate(startDateTimeArg: DateTimeArgType): DateTime | undefined {
167
+ export function findEarliestPossibleBashEventDate(
168
+ startDateTimeArg: DateTimeArgType
169
+ ): DateTime | undefined {
155
170
  return findEarliestOrLatestPossibleBashEventDate(startDateTimeArg, true);
156
171
  }
157
172
 
158
- function findEarliestOrLatestPossibleBashEventDate(startDateTimeArg: DateTimeArgType, findEarly: boolean): DateTime | undefined {
173
+ function findEarliestOrLatestPossibleBashEventDate(
174
+ startDateTimeArg: DateTimeArgType,
175
+ findEarly: boolean
176
+ ): DateTime | undefined {
159
177
  if (!startDateTimeArg) {
160
178
  return;
161
179
  }
162
180
  // Don't allow dates before the current date
163
- const startDateTime = DateTime.fromJSDate(new Date(startDateTimeArg));
181
+ const startDateTime = dateTimeFromDate(startDateTimeArg);
164
182
  const currentDateTime = DateTime.local();
165
- const comparedDateTime = compareDateTime(currentDateTime.toJSDate(), startDateTimeArg);
183
+ const comparedDateTime = compareDateTime(
184
+ currentDateTime.toJSDate(),
185
+ startDateTimeArg
186
+ );
166
187
  if (findEarly) {
167
188
  return comparedDateTime > 0 ? currentDateTime : startDateTime;
168
- }
169
- else {
189
+ } else {
170
190
  return comparedDateTime < 0 ? currentDateTime : startDateTime;
171
191
  }
172
192
  }