Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
mup committed Feb 4, 2025
1 parent e3da4ff commit a0e43a2
Show file tree
Hide file tree
Showing 2 changed files with 304 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/common/calendar/date/CalendarUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1311,9 +1311,9 @@ export function findNextAlarmOccurrence(
repeatRule: RepeatRule,
): AlarmOccurrence | null {
let occurrenceNumber = 0
const exclusions = repeatRule.excludedDates.map(({ date }) => date)
const isAllDayEvent = isAllDayEventByTimes(eventStart, eventEnd)
const calcEventStart = isAllDayEvent ? getAllDayDateForTimezone(eventStart, localTimeZone) : eventStart
const exclusions = repeatRule.excludedDates.map(({ date }) => date)
let calcEventStart = isAllDayEvent ? getAllDayDateForTimezone(eventStart, localTimeZone) : eventStart
assertDateIsValid(calcEventStart)

const endDate =
Expand Down Expand Up @@ -1341,7 +1341,7 @@ export function findNextAlarmOccurrence(
endTime: eventEnd,
repeatRule,
} as StrippedEntity<CalendarEvent>),
timeZone,
localTimeZone,
maxDate,
)

Expand Down
301 changes: 301 additions & 0 deletions test/tests/calendar/CalendarUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
AlarmInterval,
AlarmIntervalUnit,
AlarmOccurrence,
ByRule,
calendarEventHasMoreThanOneOccurrencesLeft,
CalendarEventValidity,
CalendarMonth,
Expand Down Expand Up @@ -39,10 +40,12 @@ import {
} from "../../../src/common/api/common/utils/CommonCalendarUtils.js"
import { hasCapabilityOnGroup } from "../../../src/common/sharing/GroupUtils.js"
import {
AdvancedRepeatRule,
CalendarEvent,
CalendarEventAttendeeTypeRef,
CalendarEventTypeRef,
CalendarRepeatRuleTypeRef,
createAdvancedRepeatRule,
createCalendarRepeatRule,
EncryptedMailAddressTypeRef,
UserSettingsGroupRootTypeRef,
Expand All @@ -59,6 +62,7 @@ import { EventType } from "../../../src/calendar-app/calendar/gui/eventeditor-mo
import { CalendarInfo } from "../../../src/calendar-app/calendar/model/CalendarModel.js"
import { Time } from "../../../src/common/calendar/date/Time.js"
import type { UserController } from "../../../src/common/api/main/UserController.js"
import { StrippedEntity } from "../../../src/common/api/common/utils/EntityUtils.js"

const zone = "Europe/Berlin"

Expand Down Expand Up @@ -603,6 +607,302 @@ o.spec("calendar utils tests", function () {
).toJSDate(),
])
})
o("weekly never ends with by rules", function () {
const now = DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 0,
},
{ zone: timeZone },
).toJSDate()
const eventStart = DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 12,
},
{ zone: timeZone },
).toJSDate()
const eventEnd = DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 14,
},
{ zone: timeZone },
).toJSDate()
const occurrences = iterateAlarmOccurrences(
now,
timeZone,
eventStart,
eventEnd,
StandardAlarmInterval.ONE_HOUR,
timeZone,
10,
createCalendarRepeatRule({
timeZone: timeZone,
frequency: RepeatPeriod.WEEKLY,
interval: String(1),
endValue: null,
endType: "0",
excludedDates: [],
advancedRules: [
createAdvancedRepeatRule({
interval: "TU",
ruleType: ByRule.BYDAY,
} as StrippedEntity<AdvancedRepeatRule>),
createAdvancedRepeatRule({
interval: "MO",
ruleType: ByRule.BYDAY,
} as StrippedEntity<AdvancedRepeatRule>),
],
}),
)
o(occurrences.slice(0, 5)).deepEquals([
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 3,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 4,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 10,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 11,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
])
})
o("monthly never ends with by rules", function () {
const now = DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 0,
},
{ zone: timeZone },
).toJSDate()
const eventStart = DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 12,
},
{ zone: timeZone },
).toJSDate()
const eventEnd = DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 14,
},
{ zone: timeZone },
).toJSDate()
const occurrences = iterateAlarmOccurrences(
now,
timeZone,
eventStart,
eventEnd,
StandardAlarmInterval.ONE_HOUR,
timeZone,
10,
createCalendarRepeatRule({
timeZone: timeZone,
frequency: RepeatPeriod.MONTHLY,
interval: String(1),
endValue: null,
endType: "0",
excludedDates: [],
advancedRules: [
createAdvancedRepeatRule({
interval: "TU",
ruleType: ByRule.BYDAY,
} as StrippedEntity<AdvancedRepeatRule>),
createAdvancedRepeatRule({
interval: "MO",
ruleType: ByRule.BYDAY,
} as StrippedEntity<AdvancedRepeatRule>),
],
}),
)
o(occurrences.slice(0, 5)).deepEquals([
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 3,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 4,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 10,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 11,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
])
})
o("monthly never ends on firsth monday", function () {
const now = DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 0,
},
{ zone: timeZone },
).toJSDate()
const eventStart = DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 12,
},
{ zone: timeZone },
).toJSDate()
const eventEnd = DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 14,
},
{ zone: timeZone },
).toJSDate()
const occurrences = iterateAlarmOccurrences(
now,
timeZone,
eventStart,
eventEnd,
StandardAlarmInterval.ONE_HOUR,
timeZone,
10,
createCalendarRepeatRule({
timeZone: timeZone,
frequency: RepeatPeriod.MONTHLY,
interval: String(1),
endValue: null,
endType: "0",
excludedDates: [],
advancedRules: [
createAdvancedRepeatRule({
interval: "1MO",
ruleType: ByRule.BYDAY,
} as StrippedEntity<AdvancedRepeatRule>),
],
}),
)
o(occurrences.slice(0, 4)).deepEquals([
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 1,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 2,
day: 3,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 3,
day: 3,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
DateTime.fromObject(
{
year: 2025,
month: 4,
day: 7,
hour: 11,
},
{ zone: timeZone },
).toJSDate(),
])
})
o("ends for all-day event correctly", function () {
const repeatRuleTimeZone = "Asia/Anadyr" // +12

Expand All @@ -614,6 +914,7 @@ o.spec("calendar utils tests", function () {
},
{ zone: timeZone },
).toJSDate()

// UTC date just encodes the date, whatever you pass to it. You just have to extract consistently
const eventStart = getAllDayDateUTC(
DateTime.fromObject({
Expand Down

0 comments on commit a0e43a2

Please sign in to comment.