chore: release v0.38.2
Fix recurring events with FREQ=WEEKLY;INTERVAL=N;BYDAY ignoring the interval when crossing a week boundary (e.g. Friday → Monday). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.38.2] - 2026-04-30
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Recurring calendar events with `FREQ=WEEKLY;INTERVAL=N;BYDAY=...` (N > 1) now correctly skip N−1 weeks between occurrences instead of repeating every week
|
||||||
|
|
||||||
## [0.38.1] - 2026-04-30
|
## [0.38.1] - 2026-04-30
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "oikos",
|
"name": "oikos",
|
||||||
"version": "0.38.1",
|
"version": "0.38.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "oikos",
|
"name": "oikos",
|
||||||
"version": "0.38.1",
|
"version": "0.38.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcrypt": "^6.0.0",
|
"bcrypt": "^6.0.0",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "oikos",
|
"name": "oikos",
|
||||||
"version": "0.38.1",
|
"version": "0.38.2",
|
||||||
"description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.",
|
"description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.",
|
||||||
"main": "server/index.js",
|
"main": "server/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -78,7 +78,13 @@ function nextOccurrence(baseDateStr, rrule) {
|
|||||||
});
|
});
|
||||||
// Tage bis zum nächsten Vorkommen (mind. 1, damit nicht derselbe Tag)
|
// Tage bis zum nächsten Vorkommen (mind. 1, damit nicht derselbe Tag)
|
||||||
let daysUntil = (sorted[0] - currentDay + 7) % 7;
|
let daysUntil = (sorted[0] - currentDay + 7) % 7;
|
||||||
if (daysUntil === 0) daysUntil = 7 * interval;
|
if (daysUntil === 0) {
|
||||||
|
// Selber Wochentag → ganzes Intervall überspringen
|
||||||
|
daysUntil = 7 * interval;
|
||||||
|
} else if ((sorted[0] + 6) % 7 < (currentDay + 6) % 7) {
|
||||||
|
// Wochengrenze überschritten (ISO-Woche MO–SO) → interval-1 Wochen extra überspringen
|
||||||
|
daysUntil += 7 * (interval - 1);
|
||||||
|
}
|
||||||
next.setUTCDate(next.getUTCDate() + daysUntil);
|
next.setUTCDate(next.getUTCDate() + daysUntil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -251,6 +251,33 @@ test('Monatsbereich: 42 Tage für Kalenderraster', () => {
|
|||||||
assert(to === '2026-04-11', `Erwartet 2026-04-11, erhalten ${to}`);
|
assert(to === '2026-04-11', `Erwartet 2026-04-11, erhalten ${to}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
// nextOccurrence: INTERVAL-Korrektheit mit BYDAY
|
||||||
|
// --------------------------------------------------------
|
||||||
|
import { nextOccurrence } from './server/services/recurrence.js';
|
||||||
|
|
||||||
|
test('nextOccurrence: WEEKLY BYDAY=MO,TU,WE,TH,FR INTERVAL=2 — kein täglicher Übergang', () => {
|
||||||
|
const rule = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;INTERVAL=2';
|
||||||
|
// Innerhalb der Woche: Mo→Di (1 Tag, kein Intervallsprung)
|
||||||
|
assert(nextOccurrence('2026-05-04', rule) === '2026-05-05', 'Mo→Di');
|
||||||
|
// Innerhalb der Woche: Di→Mi
|
||||||
|
assert(nextOccurrence('2026-05-05', rule) === '2026-05-06', 'Di→Mi');
|
||||||
|
// Freitag → Montag der übernächsten Woche (3 + 7 = 10 Tage)
|
||||||
|
assert(nextOccurrence('2026-05-08', rule) === '2026-05-18', 'Fr→Mo (übernächste Woche)');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('nextOccurrence: WEEKLY BYDAY=SA,SU INTERVAL=2 — Wochenend-Pair bleibt zusammen', () => {
|
||||||
|
const rule = 'FREQ=WEEKLY;BYDAY=SA,SU;INTERVAL=2';
|
||||||
|
// Sa→So (1 Tag, gleiche Woche)
|
||||||
|
assert(nextOccurrence('2026-05-09', rule) === '2026-05-10', 'Sa→So');
|
||||||
|
// So→Sa der übernächsten Woche (13 Tage)
|
||||||
|
assert(nextOccurrence('2026-05-10', rule) === '2026-05-23', 'So→Sa (übernächste Woche)');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('nextOccurrence: WEEKLY BYDAY=MO INTERVAL=2 — klassisch alle 2 Wochen', () => {
|
||||||
|
assert(nextOccurrence('2026-05-04', 'FREQ=WEEKLY;BYDAY=MO;INTERVAL=2') === '2026-05-18', 'Mo→Mo+14');
|
||||||
|
});
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
// Ergebnis
|
// Ergebnis
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user