@forcecalendar/core 1.0.4 → 1.0.6
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/core/calendar/Calendar.js +2 -2
- package/core/calendar/DateUtils.js +12 -8
- package/core/events/Event.js +3 -2
- package/core/events/EventStore.js +4 -3
- package/core/events/RecurrenceEngine.js +1 -1
- package/core/events/RecurrenceEngineV2.js +2 -1
- package/core/timezone/TimezoneManager.js +26 -0
- package/package.json +1 -1
|
@@ -15,8 +15,8 @@ export class Calendar {
|
|
|
15
15
|
* @param {import('../../types.js').CalendarConfig} [config={}] - Configuration options
|
|
16
16
|
*/
|
|
17
17
|
constructor(config = {}) {
|
|
18
|
-
// Initialize timezone manager first
|
|
19
|
-
this.timezoneManager =
|
|
18
|
+
// Initialize timezone manager first (use singleton to share cache)
|
|
19
|
+
this.timezoneManager = TimezoneManager.getInstance();
|
|
20
20
|
|
|
21
21
|
// Initialize configuration
|
|
22
22
|
this.config = {
|
|
@@ -37,8 +37,9 @@ export class DateUtils {
|
|
|
37
37
|
const day = result.getDay();
|
|
38
38
|
const diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
|
|
39
39
|
|
|
40
|
-
// Use
|
|
41
|
-
|
|
40
|
+
// Use setDate() to handle DST transitions correctly
|
|
41
|
+
// (millisecond arithmetic fails when days are 23 or 25 hours)
|
|
42
|
+
result.setDate(result.getDate() - diff);
|
|
42
43
|
result.setHours(0, 0, 0, 0);
|
|
43
44
|
return result;
|
|
44
45
|
}
|
|
@@ -51,8 +52,9 @@ export class DateUtils {
|
|
|
51
52
|
*/
|
|
52
53
|
static endOfWeek(date, weekStartsOn = 0) {
|
|
53
54
|
const result = DateUtils.startOfWeek(date, weekStartsOn);
|
|
54
|
-
// Use
|
|
55
|
-
|
|
55
|
+
// Use setDate() to handle DST transitions correctly
|
|
56
|
+
// (millisecond arithmetic fails when days are 23 or 25 hours)
|
|
57
|
+
result.setDate(result.getDate() + 6);
|
|
56
58
|
result.setHours(23, 59, 59, 999);
|
|
57
59
|
return result;
|
|
58
60
|
}
|
|
@@ -101,8 +103,9 @@ export class DateUtils {
|
|
|
101
103
|
*/
|
|
102
104
|
static addDays(date, days) {
|
|
103
105
|
const result = new Date(date);
|
|
104
|
-
// Use
|
|
105
|
-
|
|
106
|
+
// Use setDate() to handle DST transitions correctly
|
|
107
|
+
// (millisecond arithmetic fails when days are 23 or 25 hours)
|
|
108
|
+
result.setDate(result.getDate() + days);
|
|
106
109
|
return result;
|
|
107
110
|
}
|
|
108
111
|
|
|
@@ -402,8 +405,9 @@ export class DateUtils {
|
|
|
402
405
|
|
|
403
406
|
while (current.getTime() <= endTime) {
|
|
404
407
|
dates.push(new Date(current));
|
|
405
|
-
// Use
|
|
406
|
-
|
|
408
|
+
// Use setDate() to handle DST transitions correctly
|
|
409
|
+
// (millisecond arithmetic fails when days are 23 or 25 hours)
|
|
410
|
+
current.setDate(current.getDate() + 1);
|
|
407
411
|
}
|
|
408
412
|
|
|
409
413
|
return dates;
|
package/core/events/Event.js
CHANGED
|
@@ -221,8 +221,9 @@ export class Event {
|
|
|
221
221
|
this.id = normalized.id;
|
|
222
222
|
this.title = normalized.title;
|
|
223
223
|
|
|
224
|
-
//
|
|
225
|
-
|
|
224
|
+
// Use shared timezone manager singleton to avoid memory bloat
|
|
225
|
+
// (previously each Event created its own TimezoneManager instance)
|
|
226
|
+
this._timezoneManager = TimezoneManager.getInstance();
|
|
226
227
|
|
|
227
228
|
// Timezone handling
|
|
228
229
|
// Store the timezone the event was created in (wall-clock time)
|
|
@@ -30,8 +30,8 @@ export class EventStore {
|
|
|
30
30
|
byStatus: new Map()
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
// Timezone manager for conversions
|
|
34
|
-
this.timezoneManager =
|
|
33
|
+
// Timezone manager for conversions (use singleton to share cache)
|
|
34
|
+
this.timezoneManager = TimezoneManager.getInstance();
|
|
35
35
|
|
|
36
36
|
// Default timezone for the store (can be overridden)
|
|
37
37
|
this.defaultTimezone = config.timezone || this.timezoneManager.getSystemTimezone();
|
|
@@ -367,7 +367,8 @@ export class EventStore {
|
|
|
367
367
|
// Collect all events from those dates
|
|
368
368
|
const checkedIds = new Set();
|
|
369
369
|
dates.forEach(date => {
|
|
370
|
-
|
|
370
|
+
// Use getLocalDateString to match the index key format (YYYY-MM-DD)
|
|
371
|
+
const dateStr = DateUtils.getLocalDateString(date);
|
|
371
372
|
const eventIds = this.indices.byDate.get(dateStr) || new Set();
|
|
372
373
|
|
|
373
374
|
eventIds.forEach(id => {
|
|
@@ -25,7 +25,7 @@ export class RecurrenceEngine {
|
|
|
25
25
|
const occurrences = [];
|
|
26
26
|
const duration = event.end - event.start;
|
|
27
27
|
const eventTimezone = timezone || event.timeZone || 'UTC';
|
|
28
|
-
const tzManager =
|
|
28
|
+
const tzManager = TimezoneManager.getInstance();
|
|
29
29
|
|
|
30
30
|
// Work in event's timezone for accurate recurrence calculation
|
|
31
31
|
let currentDate = new Date(event.start);
|
|
@@ -8,7 +8,8 @@ import { RRuleParser } from './RRuleParser.js';
|
|
|
8
8
|
|
|
9
9
|
export class RecurrenceEngineV2 {
|
|
10
10
|
constructor() {
|
|
11
|
-
|
|
11
|
+
// Use singleton to share cache across all components
|
|
12
|
+
this.tzManager = TimezoneManager.getInstance();
|
|
12
13
|
|
|
13
14
|
// Cache for expanded occurrences
|
|
14
15
|
this.occurrenceCache = new Map();
|
|
@@ -7,7 +7,33 @@
|
|
|
7
7
|
|
|
8
8
|
import { TimezoneDatabase } from './TimezoneDatabase.js';
|
|
9
9
|
|
|
10
|
+
// Singleton instance for shared use across the application
|
|
11
|
+
let sharedInstance = null;
|
|
12
|
+
|
|
10
13
|
export class TimezoneManager {
|
|
14
|
+
/**
|
|
15
|
+
* Get the shared singleton instance of TimezoneManager
|
|
16
|
+
* This should be used instead of creating new instances to avoid memory bloat
|
|
17
|
+
* @returns {TimezoneManager} The shared instance
|
|
18
|
+
*/
|
|
19
|
+
static getInstance() {
|
|
20
|
+
if (!sharedInstance) {
|
|
21
|
+
sharedInstance = new TimezoneManager();
|
|
22
|
+
}
|
|
23
|
+
return sharedInstance;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Reset the singleton instance (useful for testing)
|
|
28
|
+
* @private
|
|
29
|
+
*/
|
|
30
|
+
static _resetInstance() {
|
|
31
|
+
if (sharedInstance) {
|
|
32
|
+
sharedInstance.clearCache();
|
|
33
|
+
}
|
|
34
|
+
sharedInstance = null;
|
|
35
|
+
}
|
|
36
|
+
|
|
11
37
|
constructor() {
|
|
12
38
|
// Initialize comprehensive timezone database
|
|
13
39
|
this.database = new TimezoneDatabase();
|