@adobe/spacecat-shared-utils 1.57.1 → 1.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [@adobe/spacecat-shared-utils-v1.58.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.57.1...@adobe/spacecat-shared-utils-v1.58.0) (2025-10-09)
2
+
3
+
4
+ ### Features
5
+
6
+ * introduce ISO calendar calculations ([#1015](https://github.com/adobe/spacecat-shared/issues/1015)) ([885351f](https://github.com/adobe/spacecat-shared/commit/885351f67cae1ea07beea0489c737e6990d93324))
7
+
1
8
  # [@adobe/spacecat-shared-utils-v1.57.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-utils-v1.57.0...@adobe/spacecat-shared-utils-v1.57.1) (2025-10-09)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-utils",
3
- "version": "1.57.1",
3
+ "version": "1.58.0",
4
4
  "description": "Shared modules of the Spacecat Services - utils",
5
5
  "type": "module",
6
6
  "exports": {
@@ -241,3 +241,108 @@ export function getLastNumberOfWeeks(number) {
241
241
 
242
242
  return result;
243
243
  }
244
+
245
+ /**
246
+ * Checks if the given date is in the last calendar week of the previous year
247
+ * @param {number} utcMonth - The UTC month as retrieved from date.getUTCMonth()
248
+ * @param {number} utcDate - The UTC date as retrieved from date.getUTCDate()
249
+ * @param {number} utcDay - The UTC day of the week as retrieved from date.getUTCDay()
250
+ * @return {boolean} - if the date is in the previous year's last calendar week.
251
+ */
252
+ function isInPreviousCalendarYear(utcMonth, utcDate, utcDay) {
253
+ return (
254
+ utcMonth === 0 // January
255
+ && utcDate < 4 // before 4th January
256
+ && ((utcDay + 6) % 7) > (utcDate + 2) // 1st: Fr, Sa, Su; 2nd: Sa, Su; 3rd: Su
257
+ );
258
+ }
259
+
260
+ /**
261
+ * Calculates the start date of the ISO calendar week for a given date.
262
+ * This is the date of the Monday at 00:00 of the ISO week that contains the given date.
263
+ * @param {number} utcFullYear - The UTC month as retrieved from date.getUTCFullYear()
264
+ * @param {number} utcMonth - The UTC month as retrieved from date.getUTCMonth()
265
+ * @param {number} utcDate - The UTC date as retrieved from date.getUTCDate()
266
+ * @returns {Date} - The start date of the ISO calendar week.
267
+ */
268
+ function isoCalendarWeekStart(utcFullYear, utcMonth, utcDate) {
269
+ const utcMidnight = Date.UTC(utcFullYear, utcMonth, utcDate);
270
+ const utcDay = new Date(utcMidnight).getUTCDay();
271
+
272
+ // Adjust to Monday
273
+ return new Date(utcMidnight - ((utcDay + 6) % 7) * MILLIS_IN_DAY);
274
+ }
275
+
276
+ /**
277
+ * Checks whether the given date is in the first calendar week of the next year
278
+ * @param {number} utcMonth - The UTC month as retrieved from date.getUTCMonth()
279
+ * @param {number} utcDate - The UTC date as retrieved from date.getUTCDate()
280
+ * @param {number} utcDay - The UTC day of the week as retrieved from date.getUTCDay()
281
+ * @return {boolean} - if the date is in the next year's calendar week 1.
282
+ */
283
+ function isInNextCalendarYear(utcMonth, utcDate, utcDay) {
284
+ return (
285
+ utcMonth === 11 // December
286
+ && utcDate > 28 // after 28th December
287
+ // 29th: Mo, 30th: Mo, Tu, 31st: Mo, Tu, We
288
+ && (utcDate - 28) > ((utcDay + 6) % 7)
289
+ );
290
+ }
291
+
292
+ /**
293
+ * Calculates the start date of the ISO calendar week for a given date.
294
+ * This is the date of the Monday at 00:00 of the ISO week that contains the given date.
295
+ * @param {Date} date - The date to calculate the ISO calendar week start for.
296
+ * @returns {Date} - The start date of the ISO calendar week.
297
+ */
298
+ export function isoCalendarWeekMonday(date) {
299
+ return isoCalendarWeekStart(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
300
+ }
301
+
302
+ /**
303
+ * Calculates the end date of the ISO calendar week for a given date.
304
+ * This is the date of the Sunday at 23:59:59.999 of the ISO week that contains the given date.
305
+ * @param {Date} date - The date to calculate the ISO calendar week start for.
306
+ * @returns {Date} - The end date/time of the ISO calendar week.
307
+ */
308
+ export function isoCalendarWeekSunday(date) {
309
+ const monday = isoCalendarWeekStart(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
310
+ return new Date(+monday + MILLIS_IN_WEEK - 1);
311
+ }
312
+
313
+ /**
314
+ * Calculates the calendar week according to ISO 8601:
315
+ * - Weeks start with Monday and end on Sunday.
316
+ * - Each week's year is the Gregorian year in which the Thursday falls.
317
+ * - It is the first week with a majority (4 or more) of its days in January.
318
+ * - Its first day is the Monday nearest to 1 January.
319
+ * - It has 4 January in it.
320
+ * Hence the earliest possible first week extends
321
+ * - from Monday 29 December (previous Gregorian year) to Sunday 4 January,
322
+ * - the latest possible first week extends from Monday 4 January to Sunday 10 January.
323
+ *
324
+ * See: https://en.wikipedia.org/wiki/ISO_week_date
325
+ *
326
+ * @param {Date} date
327
+ * @returns {ISOCalendarWeek}
328
+ */
329
+ export function isoCalendarWeek(date) {
330
+ const utcDay = date.getUTCDay();
331
+ const utcDate = date.getUTCDate();
332
+ const utcMonth = date.getUTCMonth();
333
+ const utcYear = date.getUTCFullYear();
334
+
335
+ if (isInNextCalendarYear(utcMonth, utcDate, utcDay)) {
336
+ return { week: 1, year: utcYear + 1 };
337
+ }
338
+
339
+ if (isInPreviousCalendarYear(utcMonth, utcDate, utcDay)) {
340
+ return isoCalendarWeek(isoCalendarWeekStart(utcYear, utcMonth, utcMonth));
341
+ }
342
+
343
+ // same calendar year
344
+
345
+ const weekOneStart = isoCalendarWeekStart(utcYear, 0, 4);
346
+ const weekZeroBased = Math.trunc((+date - +weekOneStart) / MILLIS_IN_WEEK);
347
+ return { week: weekZeroBased + 1, year: utcYear };
348
+ }