mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 03:14:40 +03:00
Fix recurrence rule parser (#3597)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
ddd23e3bdf
commit
0ed468caba
@ -65,7 +65,7 @@ function generateDailyValues (
|
||||
|
||||
currentDate.setDate(currentDate.getDate() + (interval ?? 1))
|
||||
if (count !== undefined && i === count) break
|
||||
if (endDate !== undefined && currentDate.getTime() > endDate) break
|
||||
if (endDate != null && currentDate.getTime() > endDate) break
|
||||
if (currentDate.getTime() > to) break
|
||||
}
|
||||
}
|
||||
@ -78,16 +78,20 @@ function generateWeeklyValues (
|
||||
to: Timestamp
|
||||
): void {
|
||||
const { count, endDate, interval } = rule
|
||||
const { byDay, wkst, bySetPos } = rule
|
||||
let { byDay, wkst, bySetPos } = rule
|
||||
let i = 0
|
||||
|
||||
if (byDay === undefined) {
|
||||
byDay = [getWeekday(currentDate, wkst)]
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const next = new Date(currentDate).setDate(currentDate.getDate() + (interval ?? 1) * 7)
|
||||
const end = new Date(new Date(currentDate).setDate(currentDate.getDate() + 7))
|
||||
let date = currentDate
|
||||
while (date < end) {
|
||||
if (
|
||||
(byDay == null || byDay.includes(getWeekday(date, wkst))) &&
|
||||
(byDay == null || matchesByDay(date, byDay, wkst)) &&
|
||||
(bySetPos == null || bySetPos.includes(getSetPos(date)))
|
||||
) {
|
||||
const res = date.getTime()
|
||||
@ -98,7 +102,7 @@ function generateWeeklyValues (
|
||||
}
|
||||
date = new Date(date.setDate(date.getDate() + 1))
|
||||
if (count !== undefined && i === count) return
|
||||
if (endDate !== undefined && date.getTime() > endDate) return
|
||||
if (endDate != null && date.getTime() > endDate) return
|
||||
if (date.getTime() > to) return
|
||||
}
|
||||
|
||||
@ -106,6 +110,45 @@ function generateWeeklyValues (
|
||||
}
|
||||
}
|
||||
|
||||
function matchesByDay (date: Date, byDay: string[], wkst: string | undefined): boolean {
|
||||
const weekday = getWeekday(date, wkst)
|
||||
const dayOfMonth = Math.floor((date.getDate() - 1) / 7) + 1
|
||||
|
||||
for (const byDayItem of byDay) {
|
||||
if (byDayItem === weekday) {
|
||||
return true
|
||||
}
|
||||
|
||||
const pos = parseInt(byDayItem)
|
||||
if (isNaN(pos)) continue
|
||||
|
||||
if (pos > 0 && dayOfMonth === pos) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (pos < 0 && dayOfMonth === getNegativePosition(date, weekday, pos)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function getNegativePosition (date: Date, weekday: string, pos: number): number | undefined {
|
||||
const lastDayOfMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate()
|
||||
const occurrences = []
|
||||
for (let day = lastDayOfMonth; day >= 1; day--) {
|
||||
const tempDate = new Date(date.getFullYear(), date.getMonth(), day)
|
||||
if (getWeekday(tempDate) === weekday) {
|
||||
occurrences.push(day)
|
||||
}
|
||||
if (occurrences.length === Math.abs(pos)) {
|
||||
return occurrences.pop()
|
||||
}
|
||||
}
|
||||
throw new Error(`Unable to calculate negative position ${pos}`)
|
||||
}
|
||||
|
||||
function generateMonthlyValues (
|
||||
rule: RecurringRule,
|
||||
currentDate: Date,
|
||||
@ -114,16 +157,20 @@ function generateMonthlyValues (
|
||||
to: Timestamp
|
||||
): void {
|
||||
const { count, endDate, interval } = rule
|
||||
const { byDay, byMonthDay, bySetPos, wkst } = rule
|
||||
let { byDay, byMonthDay, bySetPos, wkst } = rule
|
||||
let i = 0
|
||||
|
||||
if (byDay == null && byMonthDay == null) {
|
||||
byMonthDay = [currentDate.getDate()]
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const next = new Date(currentDate).setMonth(currentDate.getMonth() + (interval ?? 1))
|
||||
const end = new Date(new Date(currentDate).setMonth(currentDate.getMonth() + 1))
|
||||
let date = currentDate
|
||||
while (date < end) {
|
||||
if (
|
||||
(byDay == null || byDay.includes(getWeekday(currentDate, wkst))) &&
|
||||
(byDay == null || matchesByDay(date, byDay, wkst)) &&
|
||||
(byMonthDay == null || byMonthDay.includes(new Date(currentDate).getDate())) &&
|
||||
(bySetPos == null || bySetPos.includes(getSetPos(currentDate)))
|
||||
) {
|
||||
@ -136,7 +183,7 @@ function generateMonthlyValues (
|
||||
date = new Date(date.setDate(date.getDate() + 1))
|
||||
|
||||
if (count !== undefined && i === count) return
|
||||
if (endDate !== undefined && date.getTime() > endDate) return
|
||||
if (endDate != null && date.getTime() > endDate) return
|
||||
if (date.getTime() > to) return
|
||||
}
|
||||
currentDate = new Date(next)
|
||||
@ -160,7 +207,7 @@ function generateYearlyValues (
|
||||
let date = currentDate
|
||||
while (date < end) {
|
||||
if (
|
||||
(byDay == null || byDay.includes(getWeekday(currentDate, wkst))) &&
|
||||
(byDay == null || matchesByDay(date, byDay, wkst)) &&
|
||||
(byMonthDay == null || byMonthDay.includes(currentDate.getDate())) &&
|
||||
(byYearDay == null || byYearDay.includes(getYearDay(currentDate))) &&
|
||||
(byWeekNo == null || byWeekNo.includes(getWeekNumber(currentDate))) &&
|
||||
@ -175,7 +222,7 @@ function generateYearlyValues (
|
||||
}
|
||||
date = new Date(date.setDate(date.getDate() + 1))
|
||||
if (count !== undefined && i === count) return
|
||||
if (endDate !== undefined && date.getTime() > endDate) return
|
||||
if (endDate != null && date.getTime() > endDate) return
|
||||
if (date.getTime() > to) return
|
||||
}
|
||||
currentDate = new Date(next)
|
||||
|
Loading…
Reference in New Issue
Block a user