rrule-rust 3.0.0-alpha.9 → 3.0.0-next.2

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/README.md CHANGED
@@ -7,6 +7,8 @@
7
7
 
8
8
  `rrule-rust` is a library for handling recurrence rules, powered by Rust's high-performance [rrule](https://crates.io/crates/rrule) crate.
9
9
 
10
+ > 🚀 It provides significant performance improvements over pure JavaScript implementation, especially when working with non-UTC timezones.
11
+
10
12
  1. [Quick Start](#quick-start)
11
13
  2. [Performance](#performance)
12
14
 
@@ -42,19 +44,35 @@ const asString = set.toString(); // DTSTART;TZID=US/Eastern:19970902T090000\nFRE
42
44
 
43
45
  ## Performance
44
46
 
45
- ```
46
- Host: MacBook Pro, 14-inch, 2023
47
- OS: macOS 14.4.1 (23E224)
48
- Processor: Apple M3 Pro
49
- Memory: 36 GB LPDDR5
50
- ```
47
+ **Test Environment:**
48
+
49
+ - **Host:** MacBook Pro, 14-inch, 2023
50
+ - **OS:** macOS 14.4.1 (23E224)
51
+ - **Processor:** Apple M3 Pro
52
+ - **Memory:** 36 GB LPDDR5
53
+ - **Node.js:** v24.11.1
54
+
55
+ **Test Case:** Generating 30 daily occurrences using `rruleSet.all()`
51
56
 
52
- | | rrule | rrule-rust | |
53
- | -------- | ------------ | ------------- | ------------ |
54
- | UTC TZ | 15 904 ops/s | 108 538 ops/s | ~6x faster |
55
- | Other TZ | 260 ops/s | 106 034 ops/s | ~400x faster |
57
+ #### UTC Timezone
56
58
 
57
- You can run benchmarks using `npm run benchmark`.
59
+ | Implementation | Without Cache | With Cache |
60
+ | ---------------- | -------------- | ----------------- |
61
+ | **rrule-rust** | ~240,000 ops/s | ~14,000,000 ops/s |
62
+ | **rrule (node)** | ~20,000 ops/s | ~1,300,000 ops/s |
63
+
64
+ #### Other Timezone (Pacific/Kiritimati)
65
+
66
+ | Implementation | Without Cache | With Cache |
67
+ | ---------------- | -------------- | ----------------- |
68
+ | **rrule-rust** | ~235,000 ops/s | ~14,000,000 ops/s |
69
+ | **rrule (node)** | ~420 ops/s | ~1,300,000 ops/s |
70
+
71
+ **Run benchmarks yourself:**
72
+
73
+ ```bash
74
+ npm run benchmark
75
+ ```
58
76
 
59
77
  ## License
60
78
 
@@ -0,0 +1,15 @@
1
+ export interface OperationOptions {
2
+ disabled: boolean;
3
+ }
4
+ export declare class OperationCache {
5
+ private _disabled;
6
+ private readonly store;
7
+ constructor({ disabled }: OperationOptions);
8
+ get disabled(): boolean;
9
+ getOrSet<T>(key: string, defaultValue: T): T;
10
+ getOrCompute<T>(key: string, compute: () => T): T;
11
+ disable(): void;
12
+ enable(): void;
13
+ clear(): void;
14
+ clone(): OperationCache;
15
+ }
@@ -0,0 +1,44 @@
1
+ export class OperationCache {
2
+ constructor({ disabled }) {
3
+ this._disabled = disabled;
4
+ this.store = new Map();
5
+ }
6
+ get disabled() {
7
+ return this._disabled;
8
+ }
9
+ getOrSet(key, defaultValue) {
10
+ if (this.disabled) {
11
+ return defaultValue;
12
+ }
13
+ if (this.store.has(key)) {
14
+ return this.store.get(key);
15
+ }
16
+ this.store.set(key, defaultValue);
17
+ return defaultValue;
18
+ }
19
+ getOrCompute(key, compute) {
20
+ if (this.disabled) {
21
+ return compute();
22
+ }
23
+ if (this.store.has(key)) {
24
+ return this.store.get(key);
25
+ }
26
+ const value = compute();
27
+ this.store.set(key, value);
28
+ return value;
29
+ }
30
+ disable() {
31
+ this._disabled = true;
32
+ }
33
+ enable() {
34
+ this._disabled = false;
35
+ }
36
+ clear() {
37
+ this.store.clear();
38
+ }
39
+ clone() {
40
+ return new OperationCache({
41
+ disabled: this.disabled,
42
+ });
43
+ }
44
+ }
@@ -1,77 +1,317 @@
1
+ /**
2
+ * Represents a date without time information.
3
+ */
1
4
  export interface DateLike {
5
+ /** Year component (e.g., 2024) */
2
6
  readonly year: number;
7
+ /** Month component (1-12) */
3
8
  readonly month: number;
9
+ /** Day component (1-31) */
4
10
  readonly day: number;
5
11
  }
12
+ export type StripUtc<T extends DateTimeLike> = Omit<T, 'utc'>;
13
+ export type OptionalUtc<T extends DateTimeLike> = Omit<T, 'utc'> & {
14
+ utc?: boolean;
15
+ };
16
+ /**
17
+ * Represents a date with time information.
18
+ */
6
19
  export interface DateTimeLike {
20
+ /** Year component (e.g., 2024) */
7
21
  readonly year: number;
22
+ /** Month component (1-12) */
8
23
  readonly month: number;
24
+ /** Day component (1-31) */
9
25
  readonly day: number;
26
+ /** Hour component (0-23) */
10
27
  readonly hour: number;
28
+ /** Minute component (0-59) */
11
29
  readonly minute: number;
30
+ /** Second component (0-59) */
12
31
  readonly second: number;
32
+ /** Whether the time is in UTC */
13
33
  readonly utc: boolean;
14
34
  }
35
+ /**
36
+ * Represents time information.
37
+ */
15
38
  export interface Time {
39
+ /** Hour component (0-23) */
16
40
  readonly hour: number;
41
+ /** Minute component (0-59) */
17
42
  readonly minute: number;
43
+ /** Second component (0-59) */
18
44
  readonly second: number;
45
+ /** Whether the time is in UTC */
19
46
  readonly utc: boolean;
20
47
  }
48
+ /**
49
+ * Options for converting DateTime to plain object.
50
+ */
21
51
  export interface ToPlainDateTimeOptions {
52
+ /** Whether to exclude the `utc` field from the result */
22
53
  stripUtc?: boolean;
23
54
  }
24
55
  /**
25
- * Represents a date and time. Either local or UTC.
56
+ * Represents a date and time, either local or UTC.
57
+ *
58
+ * The generic type parameter `T` determines whether this is:
59
+ * - `DateTime<Time>` - A date with time information
60
+ * - `DateTime<undefined>` - A date without time information
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * // Create a date-only DateTime
65
+ * const date = DateTime.date(2024, 1, 15);
66
+ * console.log(date.year, date.month, date.day); // 2024, 1, 15
67
+ *
68
+ * // Create a local DateTime
69
+ * const local = DateTime.local(2024, 1, 15, 14, 30, 0);
70
+ * console.log(local.time?.utc); // false
71
+ *
72
+ * // Create a UTC DateTime
73
+ * const utc = DateTime.utc(2024, 1, 15, 14, 30, 0);
74
+ * console.log(utc.time?.utc); // true
75
+ * ```
26
76
  */
27
77
  export declare class DateTime<T extends Time | undefined> {
28
- private readonly state;
78
+ readonly year: number;
79
+ readonly month: number;
80
+ readonly day: number;
81
+ readonly time: T;
82
+ private offset?;
29
83
  private constructor();
30
- get year(): number;
31
- get month(): number;
32
- get day(): number;
33
- get time(): T;
34
84
  /**
35
85
  * Creates a new DateTime object from the given date and time components.
86
+ *
87
+ * This method can create either a date-only or date-time instance depending on the parameters.
88
+ *
89
+ * @param year - Year component (e.g., 2024)
90
+ * @param month - Month component (1-12)
91
+ * @param day - Day component (1-31)
92
+ * @param hour - Hour component (0-23), optional
93
+ * @param minute - Minute component (0-59), optional
94
+ * @param second - Second component (0-59), optional
95
+ * @param utc - Whether the time is in UTC, optional
96
+ * @returns A DateTime instance with or without time information
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * // Create a date-only DateTime
101
+ * const date = DateTime.create(2024, 1, 15);
102
+ *
103
+ * // Create a local DateTime
104
+ * const local = DateTime.create(2024, 1, 15, 14, 30, 0, false);
105
+ *
106
+ * // Create a UTC DateTime
107
+ * const utc = DateTime.create(2024, 1, 15, 14, 30, 0, true);
108
+ * ```
36
109
  */
37
110
  static create(year: number, month: number, day: number): DateTime<undefined>;
38
111
  static create(year: number, month: number, day: number, hour: number, minute: number, second: number, utc: boolean): DateTime<Time>;
39
112
  /**
40
- * Creates a new DateTime object from the given date and time components.
113
+ * Creates a new date-only DateTime object (without time information).
114
+ *
115
+ * @param year - Year component (e.g., 2024)
116
+ * @param month - Month component (1-12)
117
+ * @param day - Day component (1-31)
118
+ * @returns A DateTime instance without time information
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * const date = DateTime.date(2024, 1, 15);
123
+ * console.log(date.toString()); // "20240115"
124
+ * ```
41
125
  */
42
126
  static date(year: number, month: number, day: number): DateTime<undefined>;
43
127
  /**
128
+ * Creates a new local DateTime object (with time in local timezone).
44
129
  * This method is shorthand for `DateTime.create` with `utc` set to `false`.
130
+ *
131
+ * @param year - Year component (e.g., 2024)
132
+ * @param month - Month component (1-12)
133
+ * @param day - Day component (1-31)
134
+ * @param hour - Hour component (0-23)
135
+ * @param minute - Minute component (0-59)
136
+ * @param second - Second component (0-59)
137
+ * @returns A DateTime instance with local time
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * const value = DateTime.local(2024, 1, 15, 14, 30, 0);
142
+ * console.log(value.time.utc); // false
143
+ * console.log(value.toString()); // "20240115T143000"
144
+ * ```
45
145
  */
46
146
  static local(year: number, month: number, day: number, hour: number, minute: number, second: number): DateTime<Time>;
47
147
  /**
148
+ * Creates a new UTC DateTime object (with time in UTC timezone).
48
149
  * This method is shorthand for `DateTime.create` with `utc` set to `true`.
150
+ *
151
+ * @param year - Year component (e.g., 2024)
152
+ * @param month - Month component (1-12)
153
+ * @param day - Day component (1-31)
154
+ * @param hour - Hour component (0-23)
155
+ * @param minute - Minute component (0-59)
156
+ * @param second - Second component (0-59)
157
+ * @returns A DateTime instance with UTC time
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * const value = DateTime.utc(2024, 1, 15, 14, 30, 0);
162
+ * console.log(value.time.utc); // true
163
+ * console.log(value.toString()); // "20240115T143000Z"
164
+ * ```
49
165
  */
50
166
  static utc(year: number, month: number, day: number, hour: number, minute: number, second: number): DateTime<Time>;
51
167
  /**
52
- * Creates a new DateTime object from the given plain object.
168
+ * Creates a new DateTime object from a plain object representation.
169
+ *
170
+ * @param plain - A plain object with date or date-time components
171
+ * @returns A DateTime instance
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // From DateLike
176
+ * const date = DateTime.fromPlain({ year: 2024, month: 1, day: 15 });
177
+ *
178
+ * // From DateTimeLike
179
+ * const datetime = DateTime.fromPlain({
180
+ * year: 2024, month: 1, day: 15,
181
+ * hour: 14, minute: 30, second: 0, utc: false
182
+ * });
183
+ * ```
53
184
  */
54
- static fromPlain(plain: DateTimeLike): DateTime<Time>;
185
+ static fromPlain(plain: OptionalUtc<DateTimeLike>): DateTime<Time>;
186
+ static fromPlain(plain: StripUtc<DateTimeLike>): DateTime<Time>;
55
187
  static fromPlain(plain: DateLike): DateTime<undefined>;
56
188
  /**
57
- * Creates a new DateTime object from provided string representation of a date according to RFC 5545.
189
+ * Creates a new DateTime object from a string representation according to RFC 5545.
190
+ *
191
+ * Supported formats:
192
+ * - `YYYYMMDD` - Date only (e.g., "20240115")
193
+ * - `YYYYMMDDTHHMMSS` - Local date-time (e.g., "20240115T143000")
194
+ * - `YYYYMMDDTHHMMSSZ` - UTC date-time (e.g., "20240115T143000Z")
195
+ *
196
+ * @param str - The RFC 5545 formatted string
197
+ * @returns A DateTime instance
198
+ * @throws {TypeError} If the string format is invalid
199
+ *
200
+ * @example
201
+ * ```typescript
202
+ * // Parse date only
203
+ * const date = DateTime.fromString("20240115");
204
+ *
205
+ * // Parse local date-time
206
+ * const local = DateTime.fromString("20240115T143000");
207
+ *
208
+ * // Parse UTC date-time
209
+ * const utc = DateTime.fromString("20240115T143000Z");
210
+ * ```
58
211
  */
59
212
  static fromString(str: string): DateTime<Time> | DateTime<undefined>;
60
213
  /**
61
- * Converts DateTime into a plain object.
214
+ * Converts the DateTime into a plain object representation.
215
+ *
216
+ * @param options - Conversion options
217
+ * @param options.stripUtc - If true, excludes the `utc` field from the result
218
+ * @returns A plain object with date or date-time components
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * const utc = DateTime.utc(2024, 1, 15, 14, 30, 0);
223
+ *
224
+ * // With utc field
225
+ * const plain1 = utc.toPlain();
226
+ * // { year: 2024, month: 1, day: 15, hour: 14, minute: 30, second: 0, utc: true }
227
+ *
228
+ * // Without utc field
229
+ * const plain2 = utc.toPlain({ stripUtc: true });
230
+ * // { year: 2024, month: 1, day: 15, hour: 14, minute: 30, second: 0 }
231
+ *
232
+ * // Date-only DateTime
233
+ * const date = DateTime.date(2024, 1, 15);
234
+ * const plain3 = date.toPlain();
235
+ * // { year: 2024, month: 1, day: 15 }
236
+ * ```
62
237
  */
63
- toPlain<DTL extends DateTimeLike>(options?: ToPlainDateTimeOptions & {
238
+ toPlain(options: ToPlainDateTimeOptions & {
64
239
  stripUtc: false;
65
- }): DTL;
66
- toPlain<DTL extends Omit<DateTimeLike, 'utc'>>(options?: ToPlainDateTimeOptions & {
240
+ }): T extends Time ? DateTimeLike : DateLike;
241
+ toPlain(options: ToPlainDateTimeOptions & {
67
242
  stripUtc: true;
68
- }): DTL;
69
- toPlain<DTL extends DateLike>(): DTL;
243
+ }): T extends Time ? StripUtc<DateTimeLike> : DateLike;
244
+ toPlain(): T extends Time ? DateTimeLike : DateLike;
70
245
  /**
71
- * Converts DateTime into ISO 8601 string:
72
- * * `YYYYMMDD` for date only
73
- * - `YYYYMMDDTHHMMSSZ` for UTC
74
- * - `YYYYMMDDTHHMMSS` for local
246
+ * Converts the DateTime into an RFC 5545 formatted string.
247
+ *
248
+ * Format depends on the DateTime type:
249
+ * - `YYYYMMDD` for date only
250
+ * - `YYYYMMDDTHHMMSSZ` for UTC date-time
251
+ * - `YYYYMMDDTHHMMSS` for local date-time
252
+ *
253
+ * @returns An RFC 5545 formatted string
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * const date = DateTime.date(2024, 1, 15);
258
+ * console.log(date.toString()); // "20240115"
259
+ *
260
+ * const local = DateTime.local(2024, 1, 15, 14, 30, 0);
261
+ * console.log(local.toString()); // "20240115T143000"
262
+ *
263
+ * const utc = DateTime.utc(2024, 1, 15, 14, 30, 0);
264
+ * console.log(utc.toString()); // "20240115T143000Z"
265
+ * ```
75
266
  */
76
267
  toString(): string;
268
+ /**
269
+ * Converts the DateTime to a Unix timestamp in milliseconds.
270
+ *
271
+ * This method requires timezone offset information to be available. The offset
272
+ * is automatically set for:
273
+ * - DateTime instances with `utc: true`
274
+ * - DateTime instances generated by RRule methods (`all`, `between`, or iteration)
275
+ *
276
+ * @returns The Unix timestamp in milliseconds since January 1, 1970 00:00:00 UTC
277
+ * @throws {Error} If timezone offset information is not available
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * const utc = DateTime.utc(2024, 1, 15, 14, 30, 0);
282
+ * const timestamp = utc.toTimestamp();
283
+ * console.log(timestamp); // 1705328400000
284
+ *
285
+ * // DateTime from RRule methods have offset information
286
+ * const rrule = new RRule({ freq: Frequency.Daily, dtstart: DateTime.local(2024, 1, 1, 10, 0, 0) });
287
+ * const occurrences = rrule.all();
288
+ * const timestamp2 = occurrences[0].toTimestamp();
289
+ * ```
290
+ */
291
+ toTimestamp(): number;
292
+ /**
293
+ * Converts the DateTime to a JavaScript Date object.
294
+ *
295
+ * This method requires timezone offset information to be available. The offset
296
+ * is automatically set for:
297
+ * - DateTime instances with `utc: true`
298
+ * - DateTime instances generated by RRule methods (`all`, `between`, or iteration)
299
+ *
300
+ * @returns A JavaScript Date object representing the same moment in time
301
+ * @throws {Error} If timezone offset information is not available
302
+ *
303
+ * @example
304
+ * ```typescript
305
+ * const utc = DateTime.utc(2024, 1, 15, 14, 30, 0);
306
+ * const date = utc.toDate();
307
+ * console.log(date.toISOString()); // "2024-01-15T14:30:00.000Z"
308
+ *
309
+ * // DateTime from RRule methods have offset information
310
+ * const rrule = new RRule({ freq: Frequency.Daily, dtstart: DateTime.utc(2024, 1, 1, 10, 0, 0) });
311
+ * const occurrences = rrule.all();
312
+ * const date2 = occurrences[0].toDate();
313
+ * ```
314
+ */
315
+ toDate(): Date;
316
+ private toMilliseconds;
77
317
  }