@glatam/calendar-core 1.0.5 → 1.0.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAqB,MAAM,YAAY,CAAC;AAIpF,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,yBAAyB,CAAC;AAExC;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,YAAY,GAAG,SAAS,CAUvH;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,OAAO,CAEpG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,EAAE,EACrB,WAAW,GAAE,QAAQ,EAAO,EAC5B,cAAc,SAAI,GACjB,WAAW,EAAE,CAkCf;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,IAAI,EACnB,KAAK,EAAE,YAAY,EAAE,EACrB,WAAW,GAAE,QAAQ,EAAO,EAC5B,cAAc,SAAI,GACjB,WAAW,EAAE,CAgCf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAqB,MAAM,YAAY,CAAC;AAIpF,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,qCAAqC,CAAC;AACpD,cAAc,yBAAyB,CAAC;AAExC;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,YAAY,GAAG,SAAS,CAUvH;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,OAAO,CAEpG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,EAAE,EACrB,WAAW,GAAE,QAAQ,EAAO,EAC5B,cAAc,SAAI,GACjB,WAAW,EAAE,CAsCf;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,IAAI,EACnB,KAAK,EAAE,YAAY,EAAE,EACrB,WAAW,GAAE,QAAQ,EAAO,EAC5B,cAAc,SAAI,GACjB,WAAW,EAAE,CAgCf"}
package/dist/index.js CHANGED
@@ -35,6 +35,9 @@ export function generateMonthDays(year, month, rules, slotsPerDay = [], startOfW
35
35
  const days = [];
36
36
  const currentDate = new Date(startGridDate);
37
37
  for (let i = 0; i < 42; i++) {
38
+ if (i >= 28 && i % 7 === 0 && currentDate.getMonth() !== month && currentDate > firstDayOfMonth) {
39
+ break;
40
+ }
38
41
  const dateCopy = new Date(currentDate);
39
42
  const dateString = formatISODate(dateCopy);
40
43
  const evaluatedSlots = slotsPerDay.map((slot) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockingRule, CalendarDay, TimeSlot, EvaluatedTimeSlot } from './types.js';\nimport { BlockingStrategyFactory } from './strategies/factory.js';\nimport { formatISODate, getStartOfWeek } from './utils/date-utils.js';\n\nexport * from './types.js';\nexport * from './utils/date-utils.js';\nexport * from './strategies/strategy.interface.js';\nexport * from './strategies/weekly.strategy.js';\nexport * from './strategies/date-range.strategy.js';\nexport * from './strategies/factory.js';\n\n/**\n * Checks if a specific date or time slot is blocked and returns the matching rule.\n */\nexport function getBlockingRule(date: Date, slot: TimeSlot | undefined, rules: BlockingRule[]): BlockingRule | undefined {\n for (const rule of rules) {\n const strategy = BlockingStrategyFactory.getStrategy(rule.type);\n if (slot) {\n if (strategy.isSlotBlocked(date, slot, rule)) return rule;\n } else {\n if (strategy.isDateBlocked(date, rule)) return rule;\n }\n }\n return undefined;\n}\n\nexport function isTimeBlocked(date: Date, slot: TimeSlot | undefined, rules: BlockingRule[]): boolean {\n return !!getBlockingRule(date, slot, rules);\n}\n\n/**\n * Generates an array of CalendarDay items representing a monthly calendar grid.\n */\nexport function generateMonthDays(\n year: number,\n month: number,\n rules: BlockingRule[],\n slotsPerDay: TimeSlot[] = [],\n startOfWeekDay = 0\n): CalendarDay[] {\n const firstDayOfMonth = new Date(year, month, 1);\n const startGridDate = getStartOfWeek(firstDayOfMonth, startOfWeekDay);\n\n const days: CalendarDay[] = [];\n const currentDate = new Date(startGridDate);\n\n for (let i = 0; i < 42; i++) {\n const dateCopy = new Date(currentDate);\n const dateString = formatISODate(dateCopy);\n\n const evaluatedSlots: EvaluatedTimeSlot[] = slotsPerDay.map((slot) => {\n const match = getBlockingRule(dateCopy, slot, rules);\n return { ...slot, isBlocked: !!match, rule: match };\n });\n\n const dayRule = getBlockingRule(dateCopy, undefined, rules);\n const isDayFullyBlocked = !!dayRule || (evaluatedSlots.length > 0 && evaluatedSlots.every((s) => s.isBlocked));\n\n days.push({\n dateString,\n date: dateCopy,\n isBlocked: isDayFullyBlocked,\n rule: dayRule || (evaluatedSlots.length > 0 && evaluatedSlots.every((s) => s.isBlocked) ? evaluatedSlots[0].rule : undefined),\n dayOfWeek: dateCopy.getDay(),\n dayNumber: dateCopy.getDate(),\n isCurrentMonth: dateCopy.getMonth() === month,\n slots: evaluatedSlots,\n });\n\n currentDate.setDate(currentDate.getDate() + 1);\n }\n\n return days;\n}\n\n/**\n * Generates an array of 7 CalendarDay items representing a single week view.\n */\nexport function generateWeekDays(\n referenceDate: Date,\n rules: BlockingRule[],\n slotsPerDay: TimeSlot[] = [],\n startOfWeekDay = 0\n): CalendarDay[] {\n const startOfWeek = getStartOfWeek(referenceDate, startOfWeekDay);\n const days: CalendarDay[] = [];\n const currentDate = new Date(startOfWeek);\n\n for (let i = 0; i < 7; i++) {\n const dateCopy = new Date(currentDate);\n const dateString = formatISODate(dateCopy);\n\n const evaluatedSlots: EvaluatedTimeSlot[] = slotsPerDay.map((slot) => {\n const match = getBlockingRule(dateCopy, slot, rules);\n return { ...slot, isBlocked: !!match, rule: match };\n });\n\n const dayRule = getBlockingRule(dateCopy, undefined, rules);\n const isDayFullyBlocked = !!dayRule || (evaluatedSlots.length > 0 && evaluatedSlots.every((s) => s.isBlocked));\n\n days.push({\n dateString,\n date: dateCopy,\n isBlocked: isDayFullyBlocked,\n rule: dayRule || (evaluatedSlots.length > 0 && evaluatedSlots.every((s) => s.isBlocked) ? evaluatedSlots[0].rule : undefined),\n dayOfWeek: dateCopy.getDay(),\n dayNumber: dateCopy.getDate(),\n isCurrentMonth: true,\n slots: evaluatedSlots,\n });\n\n currentDate.setDate(currentDate.getDate() + 1);\n }\n\n return days;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockingRule, CalendarDay, TimeSlot, EvaluatedTimeSlot } from './types.js';\nimport { BlockingStrategyFactory } from './strategies/factory.js';\nimport { formatISODate, getStartOfWeek } from './utils/date-utils.js';\n\nexport * from './types.js';\nexport * from './utils/date-utils.js';\nexport * from './strategies/strategy.interface.js';\nexport * from './strategies/weekly.strategy.js';\nexport * from './strategies/date-range.strategy.js';\nexport * from './strategies/factory.js';\n\n/**\n * Checks if a specific date or time slot is blocked and returns the matching rule.\n */\nexport function getBlockingRule(date: Date, slot: TimeSlot | undefined, rules: BlockingRule[]): BlockingRule | undefined {\n for (const rule of rules) {\n const strategy = BlockingStrategyFactory.getStrategy(rule.type);\n if (slot) {\n if (strategy.isSlotBlocked(date, slot, rule)) return rule;\n } else {\n if (strategy.isDateBlocked(date, rule)) return rule;\n }\n }\n return undefined;\n}\n\nexport function isTimeBlocked(date: Date, slot: TimeSlot | undefined, rules: BlockingRule[]): boolean {\n return !!getBlockingRule(date, slot, rules);\n}\n\n/**\n * Generates an array of CalendarDay items representing a monthly calendar grid.\n */\nexport function generateMonthDays(\n year: number,\n month: number,\n rules: BlockingRule[],\n slotsPerDay: TimeSlot[] = [],\n startOfWeekDay = 0\n): CalendarDay[] {\n const firstDayOfMonth = new Date(year, month, 1);\n const startGridDate = getStartOfWeek(firstDayOfMonth, startOfWeekDay);\n\n const days: CalendarDay[] = [];\n const currentDate = new Date(startGridDate);\n\n for (let i = 0; i < 42; i++) {\n if (i >= 28 && i % 7 === 0 && currentDate.getMonth() !== month && currentDate > firstDayOfMonth) {\n break;\n }\n\n const dateCopy = new Date(currentDate);\n const dateString = formatISODate(dateCopy);\n\n const evaluatedSlots: EvaluatedTimeSlot[] = slotsPerDay.map((slot) => {\n const match = getBlockingRule(dateCopy, slot, rules);\n return { ...slot, isBlocked: !!match, rule: match };\n });\n\n const dayRule = getBlockingRule(dateCopy, undefined, rules);\n const isDayFullyBlocked = !!dayRule || (evaluatedSlots.length > 0 && evaluatedSlots.every((s) => s.isBlocked));\n\n days.push({\n dateString,\n date: dateCopy,\n isBlocked: isDayFullyBlocked,\n rule: dayRule || (evaluatedSlots.length > 0 && evaluatedSlots.every((s) => s.isBlocked) ? evaluatedSlots[0].rule : undefined),\n dayOfWeek: dateCopy.getDay(),\n dayNumber: dateCopy.getDate(),\n isCurrentMonth: dateCopy.getMonth() === month,\n slots: evaluatedSlots,\n });\n\n currentDate.setDate(currentDate.getDate() + 1);\n }\n\n return days;\n}\n\n/**\n * Generates an array of 7 CalendarDay items representing a single week view.\n */\nexport function generateWeekDays(\n referenceDate: Date,\n rules: BlockingRule[],\n slotsPerDay: TimeSlot[] = [],\n startOfWeekDay = 0\n): CalendarDay[] {\n const startOfWeek = getStartOfWeek(referenceDate, startOfWeekDay);\n const days: CalendarDay[] = [];\n const currentDate = new Date(startOfWeek);\n\n for (let i = 0; i < 7; i++) {\n const dateCopy = new Date(currentDate);\n const dateString = formatISODate(dateCopy);\n\n const evaluatedSlots: EvaluatedTimeSlot[] = slotsPerDay.map((slot) => {\n const match = getBlockingRule(dateCopy, slot, rules);\n return { ...slot, isBlocked: !!match, rule: match };\n });\n\n const dayRule = getBlockingRule(dateCopy, undefined, rules);\n const isDayFullyBlocked = !!dayRule || (evaluatedSlots.length > 0 && evaluatedSlots.every((s) => s.isBlocked));\n\n days.push({\n dateString,\n date: dateCopy,\n isBlocked: isDayFullyBlocked,\n rule: dayRule || (evaluatedSlots.length > 0 && evaluatedSlots.every((s) => s.isBlocked) ? evaluatedSlots[0].rule : undefined),\n dayOfWeek: dateCopy.getDay(),\n dayNumber: dateCopy.getDate(),\n isCurrentMonth: true,\n slots: evaluatedSlots,\n });\n\n currentDate.setDate(currentDate.getDate() + 1);\n }\n\n return days;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"date-range.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/date-range.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,qBAAa,iBAAkB,YAAW,gBAAgB;IACxD,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO;IAQtD,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO;IActE,OAAO,CAAC,gBAAgB;CAazB"}
1
+ {"version":3,"file":"date-range.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/date-range.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,qBAAa,iBAAkB,YAAW,gBAAgB;IACxD,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO;IAQtD,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO;IActE,OAAO,CAAC,gBAAgB;CAiBzB"}
@@ -20,6 +20,9 @@ export class DateRangeStrategy {
20
20
  }
21
21
  matchesDateRange(date, rule) {
22
22
  const dateStr = formatISODate(date);
23
+ if (rule.exceptions && rule.exceptions.includes(dateStr)) {
24
+ return false;
25
+ }
23
26
  if (rule.startDate && dateStr < rule.startDate) {
24
27
  return false;
25
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"date-range.strategy.js","sourceRoot":"","sources":["../../src/strategies/date-range.strategy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE1E,MAAM,OAAO,iBAAiB;IAC5B,aAAa,CAAC,IAAU,EAAE,IAAkB;QAC1C,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,sDAAsD;QACtD,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,aAAa,CAAC,IAAU,EAAE,IAAc,EAAE,IAAkB;QAC1D,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,8EAA8E;QAC9E,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,gEAAgE;QAChE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;IAChF,CAAC;IAEO,gBAAgB,CAAC,IAAU,EAAE,IAAkB;QACrD,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpC,IAAI,IAAI,CAAC,SAAS,IAAI,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF","sourcesContent":["import { BlockingRule, TimeSlot } from '../types.js';\nimport { BlockingStrategy } from './strategy.interface.js';\nimport { formatISODate, isTimeOverlapping } from '../utils/date-utils.js';\n\nexport class DateRangeStrategy implements BlockingStrategy {\n isDateBlocked(date: Date, rule: BlockingRule): boolean {\n if (!this.matchesDateRange(date, rule)) {\n return false;\n }\n // If no slots are defined, the entire day is blocked.\n return !rule.slots || rule.slots.length === 0;\n }\n\n isSlotBlocked(date: Date, slot: TimeSlot, rule: BlockingRule): boolean {\n if (!this.matchesDateRange(date, rule)) {\n return false;\n }\n\n // If no slots are defined, the entire day is blocked, so the slot is blocked.\n if (!rule.slots || rule.slots.length === 0) {\n return true;\n }\n\n // Check if the slot overlaps with any blocked slots in the rule\n return rule.slots.some((blockedSlot) => isTimeOverlapping(slot, blockedSlot));\n }\n\n private matchesDateRange(date: Date, rule: BlockingRule): boolean {\n const dateStr = formatISODate(date);\n\n if (rule.startDate && dateStr < rule.startDate) {\n return false;\n }\n\n if (rule.endDate && dateStr > rule.endDate) {\n return false;\n }\n\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"date-range.strategy.js","sourceRoot":"","sources":["../../src/strategies/date-range.strategy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE1E,MAAM,OAAO,iBAAiB;IAC5B,aAAa,CAAC,IAAU,EAAE,IAAkB;QAC1C,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,sDAAsD;QACtD,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,aAAa,CAAC,IAAU,EAAE,IAAc,EAAE,IAAkB;QAC1D,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,8EAA8E;QAC9E,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,gEAAgE;QAChE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;IAChF,CAAC;IAEO,gBAAgB,CAAC,IAAU,EAAE,IAAkB;QACrD,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpC,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,IAAI,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF","sourcesContent":["import { BlockingRule, TimeSlot } from '../types.js';\nimport { BlockingStrategy } from './strategy.interface.js';\nimport { formatISODate, isTimeOverlapping } from '../utils/date-utils.js';\n\nexport class DateRangeStrategy implements BlockingStrategy {\n isDateBlocked(date: Date, rule: BlockingRule): boolean {\n if (!this.matchesDateRange(date, rule)) {\n return false;\n }\n // If no slots are defined, the entire day is blocked.\n return !rule.slots || rule.slots.length === 0;\n }\n\n isSlotBlocked(date: Date, slot: TimeSlot, rule: BlockingRule): boolean {\n if (!this.matchesDateRange(date, rule)) {\n return false;\n }\n\n // If no slots are defined, the entire day is blocked, so the slot is blocked.\n if (!rule.slots || rule.slots.length === 0) {\n return true;\n }\n\n // Check if the slot overlaps with any blocked slots in the rule\n return rule.slots.some((blockedSlot) => isTimeOverlapping(slot, blockedSlot));\n }\n\n private matchesDateRange(date: Date, rule: BlockingRule): boolean {\n const dateStr = formatISODate(date);\n\n if (rule.exceptions && rule.exceptions.includes(dateStr)) {\n return false;\n }\n\n if (rule.startDate && dateStr < rule.startDate) {\n return false;\n }\n\n if (rule.endDate && dateStr > rule.endDate) {\n return false;\n }\n\n return true;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"weekly.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/weekly.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,qBAAa,cAAe,YAAW,gBAAgB;IACrD,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO;IAQtD,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO;IActE,OAAO,CAAC,iBAAiB;CAkB1B"}
1
+ {"version":3,"file":"weekly.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/weekly.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAG3D,qBAAa,cAAe,YAAW,gBAAgB;IACrD,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO;IAQtD,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO;IActE,OAAO,CAAC,iBAAiB;CAsB1B"}
@@ -24,6 +24,9 @@ export class WeeklyStrategy {
24
24
  return false;
25
25
  }
26
26
  const dateStr = formatISODate(date);
27
+ if (rule.exceptions && rule.exceptions.includes(dateStr)) {
28
+ return false;
29
+ }
27
30
  if (rule.startDate && dateStr < rule.startDate) {
28
31
  return false;
29
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"weekly.strategy.js","sourceRoot":"","sources":["../../src/strategies/weekly.strategy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE1E,MAAM,OAAO,cAAc;IACzB,aAAa,CAAC,IAAU,EAAE,IAAkB;QAC1C,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACxC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,sDAAsD;QACtD,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,aAAa,CAAC,IAAU,EAAE,IAAc,EAAE,IAAkB;QAC1D,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACxC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,8EAA8E;QAC9E,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,gEAAgE;QAChE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;IAChF,CAAC;IAEO,iBAAiB,CAAC,IAAU,EAAE,IAAkB;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpC,IAAI,IAAI,CAAC,SAAS,IAAI,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF","sourcesContent":["import { BlockingRule, TimeSlot } from '../types.js';\nimport { BlockingStrategy } from './strategy.interface.js';\nimport { formatISODate, isTimeOverlapping } from '../utils/date-utils.js';\n\nexport class WeeklyStrategy implements BlockingStrategy {\n isDateBlocked(date: Date, rule: BlockingRule): boolean {\n if (!this.matchesDateAndDay(date, rule)) {\n return false;\n }\n // If no slots are defined, the entire day is blocked.\n return !rule.slots || rule.slots.length === 0;\n }\n\n isSlotBlocked(date: Date, slot: TimeSlot, rule: BlockingRule): boolean {\n if (!this.matchesDateAndDay(date, rule)) {\n return false;\n }\n\n // If no slots are defined, the entire day is blocked, so the slot is blocked.\n if (!rule.slots || rule.slots.length === 0) {\n return true;\n }\n\n // Check if the slot overlaps with any blocked slots in the rule\n return rule.slots.some((blockedSlot) => isTimeOverlapping(slot, blockedSlot));\n }\n\n private matchesDateAndDay(date: Date, rule: BlockingRule): boolean {\n const dayOfWeek = date.getDay();\n if (!rule.daysOfWeek || !rule.daysOfWeek.includes(dayOfWeek)) {\n return false;\n }\n\n const dateStr = formatISODate(date);\n\n if (rule.startDate && dateStr < rule.startDate) {\n return false;\n }\n\n if (rule.endDate && dateStr > rule.endDate) {\n return false;\n }\n\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"weekly.strategy.js","sourceRoot":"","sources":["../../src/strategies/weekly.strategy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE1E,MAAM,OAAO,cAAc;IACzB,aAAa,CAAC,IAAU,EAAE,IAAkB;QAC1C,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACxC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,sDAAsD;QACtD,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,aAAa,CAAC,IAAU,EAAE,IAAc,EAAE,IAAkB;QAC1D,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACxC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,8EAA8E;QAC9E,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,gEAAgE;QAChE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;IAChF,CAAC;IAEO,iBAAiB,CAAC,IAAU,EAAE,IAAkB;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAEpC,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,IAAI,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF","sourcesContent":["import { BlockingRule, TimeSlot } from '../types.js';\nimport { BlockingStrategy } from './strategy.interface.js';\nimport { formatISODate, isTimeOverlapping } from '../utils/date-utils.js';\n\nexport class WeeklyStrategy implements BlockingStrategy {\n isDateBlocked(date: Date, rule: BlockingRule): boolean {\n if (!this.matchesDateAndDay(date, rule)) {\n return false;\n }\n // If no slots are defined, the entire day is blocked.\n return !rule.slots || rule.slots.length === 0;\n }\n\n isSlotBlocked(date: Date, slot: TimeSlot, rule: BlockingRule): boolean {\n if (!this.matchesDateAndDay(date, rule)) {\n return false;\n }\n\n // If no slots are defined, the entire day is blocked, so the slot is blocked.\n if (!rule.slots || rule.slots.length === 0) {\n return true;\n }\n\n // Check if the slot overlaps with any blocked slots in the rule\n return rule.slots.some((blockedSlot) => isTimeOverlapping(slot, blockedSlot));\n }\n\n private matchesDateAndDay(date: Date, rule: BlockingRule): boolean {\n const dayOfWeek = date.getDay();\n if (!rule.daysOfWeek || !rule.daysOfWeek.includes(dayOfWeek)) {\n return false;\n }\n\n const dateStr = formatISODate(date);\n\n if (rule.exceptions && rule.exceptions.includes(dateStr)) {\n return false;\n }\n\n if (rule.startDate && dateStr < rule.startDate) {\n return false;\n }\n\n if (rule.endDate && dateStr > rule.endDate) {\n return false;\n }\n\n return true;\n }\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -11,7 +11,8 @@ export interface BlockingRule {
11
11
  daysOfWeek?: number[];
12
12
  slots?: TimeSlot[];
13
13
  description?: string;
14
- [key: string]: any;
14
+ exceptions?: string[];
15
+ [key: string]: unknown;
15
16
  }
16
17
  export interface CalendarDay {
17
18
  dateString: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,IAAI,CAAC;IACX,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface TimeSlot {\n start: string;\n end: string;\n}\n\nexport type BlockingRuleType = 'weekly' | 'date-range';\n\nexport interface BlockingRule {\n id: string;\n type: BlockingRuleType;\n startDate?: string;\n endDate?: string;\n daysOfWeek?: number[];\n slots?: TimeSlot[];\n description?: string; // Descriptive title/notes for the task/block\n [key: string]: any; // Allow custom metadata (assignees, status, priority)\n}\n\nexport interface CalendarDay {\n dateString: string;\n date: Date;\n isBlocked: boolean;\n rule?: BlockingRule; // The rule blocking the whole day\n dayOfWeek: number;\n dayNumber: number;\n isCurrentMonth: boolean;\n slots: EvaluatedTimeSlot[];\n}\n\nexport interface EvaluatedTimeSlot {\n start: string;\n end: string;\n isBlocked: boolean;\n rule?: BlockingRule; // The rule that caused the block\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface TimeSlot {\n start: string;\n end: string;\n}\n\nexport type BlockingRuleType = 'weekly' | 'date-range';\n\nexport interface BlockingRule {\n id: string;\n type: BlockingRuleType;\n startDate?: string;\n endDate?: string;\n daysOfWeek?: number[];\n slots?: TimeSlot[];\n description?: string; // Descriptive title/notes for the task/block\n exceptions?: string[]; // Array of YYYY-MM-DD strings for dates where this rule is overridden / unblocked\n [key: string]: unknown; // Allow custom metadata (assignees, status, priority)\n}\n\nexport interface CalendarDay {\n dateString: string;\n date: Date;\n isBlocked: boolean;\n rule?: BlockingRule; // The rule blocking the whole day\n dayOfWeek: number;\n dayNumber: number;\n isCurrentMonth: boolean;\n slots: EvaluatedTimeSlot[];\n}\n\nexport interface EvaluatedTimeSlot {\n start: string;\n end: string;\n isBlocked: boolean;\n rule?: BlockingRule; // The rule that caused the block\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"date-utils.d.ts","sourceRoot":"","sources":["../../src/utils/date-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CASlD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAKhD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAO3E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,SAAI,GAAG,IAAI,CAMnE"}
1
+ {"version":3,"file":"date-utils.d.ts","sourceRoot":"","sources":["../../src/utils/date-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CASlD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAKhD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAU3E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,SAAI,GAAG,IAAI,CAMnE"}
@@ -33,9 +33,13 @@ export function timeToMinutes(timeStr) {
33
33
  */
34
34
  export function isTimeOverlapping(slot1, slot2) {
35
35
  const start1 = timeToMinutes(slot1.start);
36
- const end1 = timeToMinutes(slot1.end);
36
+ let end1 = timeToMinutes(slot1.end);
37
+ if (end1 === 0 || slot1.end === '24:00' || end1 <= start1)
38
+ end1 = 1440;
37
39
  const start2 = timeToMinutes(slot2.start);
38
- const end2 = timeToMinutes(slot2.end);
40
+ let end2 = timeToMinutes(slot2.end);
41
+ if (end2 === 0 || slot2.end === '24:00' || end2 <= start2)
42
+ end2 = 1440;
39
43
  return start1 < end2 && start2 < end1;
40
44
  }
41
45
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"date-utils.js","sourceRoot":"","sources":["../../src/utils/date-utils.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY;IACtD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACnC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxD,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAe,EAAE,KAAe;IAChE,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEtC,OAAO,MAAM,GAAG,IAAI,IAAI,MAAM,GAAG,IAAI,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU,EAAE,cAAc,GAAG,CAAC;IAC3D,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7E,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,cAAc,CAAC;IACnE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { TimeSlot } from '../types.js';\n\n/**\n * Parses an ISO date string (YYYY-MM-DD) into a local Date object.\n * Prevents timezone shifting issues.\n */\nexport function parseISODate(dateStr: string): Date {\n const parts = dateStr.split('T')[0].split('-');\n if (parts.length !== 3) {\n return new Date(dateStr);\n }\n const year = parseInt(parts[0], 10);\n const month = parseInt(parts[1], 10) - 1; // 0-indexed\n const day = parseInt(parts[2], 10);\n return new Date(year, month, day);\n}\n\n/**\n * Formats a Date object to YYYY-MM-DD in the local timezone.\n */\nexport function formatISODate(date: Date): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\n/**\n * Converts a time string \"HH:MM\" to minutes from midnight.\n */\nexport function timeToMinutes(timeStr: string): number {\n const [hours, minutes] = timeStr.split(':').map(Number);\n return (hours || 0) * 60 + (minutes || 0);\n}\n\n/**\n * Checks if two time slots overlap.\n */\nexport function isTimeOverlapping(slot1: TimeSlot, slot2: TimeSlot): boolean {\n const start1 = timeToMinutes(slot1.start);\n const end1 = timeToMinutes(slot1.end);\n const start2 = timeToMinutes(slot2.start);\n const end2 = timeToMinutes(slot2.end);\n\n return start1 < end2 && start2 < end1;\n}\n\n/**\n * Gets the start of the week for a given date.\n * @param date The date reference.\n * @param startOfWeekDay The day the week starts (0 = Sunday, 1 = Monday). Default is 0.\n */\nexport function getStartOfWeek(date: Date, startOfWeekDay = 0): Date {\n const result = new Date(date.getFullYear(), date.getMonth(), date.getDate());\n const day = result.getDay();\n const diff = (day < startOfWeekDay ? 7 : 0) + day - startOfWeekDay;\n result.setDate(result.getDate() - diff);\n return result;\n}\n"]}
1
+ {"version":3,"file":"date-utils.js","sourceRoot":"","sources":["../../src/utils/date-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { TimeSlot } from '../types.js';\n\n/**\n * Parses an ISO date string (YYYY-MM-DD) into a local Date object.\n * Prevents timezone shifting issues.\n */\nexport function parseISODate(dateStr: string): Date {\n const parts = dateStr.split('T')[0].split('-');\n if (parts.length !== 3) {\n return new Date(dateStr);\n }\n const year = parseInt(parts[0], 10);\n const month = parseInt(parts[1], 10) - 1; // 0-indexed\n const day = parseInt(parts[2], 10);\n return new Date(year, month, day);\n}\n\n/**\n * Formats a Date object to YYYY-MM-DD in the local timezone.\n */\nexport function formatISODate(date: Date): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\n/**\n * Converts a time string \"HH:MM\" to minutes from midnight.\n */\nexport function timeToMinutes(timeStr: string): number {\n const [hours, minutes] = timeStr.split(':').map(Number);\n return (hours || 0) * 60 + (minutes || 0);\n}\n\n/**\n * Checks if two time slots overlap.\n */\nexport function isTimeOverlapping(slot1: TimeSlot, slot2: TimeSlot): boolean {\n const start1 = timeToMinutes(slot1.start);\n let end1 = timeToMinutes(slot1.end);\n if (end1 === 0 || slot1.end === '24:00' || end1 <= start1) end1 = 1440;\n\n const start2 = timeToMinutes(slot2.start);\n let end2 = timeToMinutes(slot2.end);\n if (end2 === 0 || slot2.end === '24:00' || end2 <= start2) end2 = 1440;\n\n return start1 < end2 && start2 < end1;\n}\n\n/**\n * Gets the start of the week for a given date.\n * @param date The date reference.\n * @param startOfWeekDay The day the week starts (0 = Sunday, 1 = Monday). Default is 0.\n */\nexport function getStartOfWeek(date: Date, startOfWeekDay = 0): Date {\n const result = new Date(date.getFullYear(), date.getMonth(), date.getDate());\n const day = result.getDay();\n const diff = (day < startOfWeekDay ? 7 : 0) + day - startOfWeekDay;\n result.setDate(result.getDate() - diff);\n return result;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glatam/calendar-core",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Lógica pura del calendario @glatam/calendar",
5
5
  "type": "module",
6
6
  "author": "Santiago Hernández Saldarriaga",