npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@suilang/rrule

v0.0.9

Published

The rrule parser written in rrust, specially adapted for js

Downloads

4

Readme

@suilang/rrule

Build with rust, 5 faster than rrule.js

This is a rrule project written in Rust, which is ultimately packaged as WebAssembly for use. The current version of this project does not strictly adhere to the iCalendar RFC. For example, certain properties may not take effect when the recurring dimension is monthly, weekly, or daily. Additionally, the project has not yet implemented BYHOURLYBYMINUTELY and BYSECONDLY.

In a standard scenario, it is 5 times faster than rrule.js. If you add timezone, it's 100 times faster.


Quick Start

Just install it like a normal npm package. If you are webpack4, you may need file-loader support. For webpack5, just use it.

Client Side

$ yarn add @suilang/rrule

Server Side

Server-side calls are not currently supported, although the packaging is different, but I want to integrate it into an npm package, and I will add support for nodejs later.

Usage

In es module, you must call the init function before you can use the inner function. Don't worry about performance, it may only take a few tens of milliseconds.

Init by string

import init, { JsRRuleSet } from '@suilang/rrule';

init().then(() => {
  const set = new JsRRuleSet('DTSTART:20220506T180000Z\nRRULE:FREQ=WEEKLY;WKST=SU;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;UNTIL=20231121T235959');
  set.tz('Asia/Shanghai')

  // or with timezone in string
  // DTSTART;TZID=Asia/Shanghai:20220506T180000Z\nRRULE:FREQ=WEEKLY;WKST=SU;UNTIL=20231121T235959

  set
    .all()
    .split(',')
    .map((str) => new Date(Number(str)))
})

[ "2022-05-06T10:00:00.000Z",
"2022-05-09T10:00:00.000Z",
"2022-05-10T10:00:00.000Z",
"2022-05-11T10:00:00.000Z",
"2022-05-12T10:00:00.000Z",
"2022-05-13T10:00:00.000Z",
 /* … */]

Due to a communication problem, the format returned is a timestamp concatenated string, separated by commas. Need to actively divide and parse.

You can also set start time separately in the following way:

const set = new JsRRuleSet(
  "RRULE:FREQ=WEEKLY;WKST=SU;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;UNTIL=20231121T235959"
);

set.tz("Asia/Shanghai");
set.set_dt_start("20220506T180000Z");

Init by json

Rust does not recognize js objects directly, so the data needs to be passed in JSON form.

import init, { getJsRRuleSet } from './pkg/rrule_rust.js';

const data = {
  dtStart: '20221126T091800Z',
  count: 3,
  freq: 'MONTHLY',
  interval: 2,
  until: '20231126T091800Z',
  wkst: 'MO',
  tz: 'America/New_York',
};
init().then(() => {
  const set = getJsRRuleSet(JSON.stringify(data));
  set
    .all()
    .split(',')
    .map((str) => new Date(Number(str)))
})

[ "2022-05-06T10:00:00.000Z",
"2022-05-09T10:00:00.000Z",
"2022-05-10T10:00:00.000Z",
"2022-05-11T10:00:00.000Z",
"2022-05-12T10:00:00.000Z",
"2022-05-13T10:00:00.000Z",
 /* … */]

The types of currently recognizable parameters are as follows

interface RRuleProps {
  dtStart: string; // '20231101T120000Z'
  count: number; // 3
  freq: string; // 'DAILY'
  interval: number; // 2
  byWeekNo: number[]; // [1, 2]
  byDay: string[]; // ['MO', '-1FR']
  until: string; // '20231201T120000Z'
  wkst: string; // 'SU';
  byMonthDay: number[]; // [-1, 2]
  byMonth: number[]; // [2, 3]
  byYearDay: number[]; // [1, 50]
  tz: string; // 'America/New_York'
}

Property Support

For complexity or performance reasons, I do not support all properties, some of which cause performance or understanding problems in some FREQs, and whose can be implemented in others.

The specific meanings of each parameter can be found in rrule-js.

I have not implemented the HOURLY, MINUTELY, and SECONDLY FREQ fields. The first few loops are already complicated.

The following describes the different properties supported by FREQ.

FREQ=DAILY

  • Support interval, default is 1.
  • Support count, default is 65535, but if there is not have until, will return [].
  • Support until,and if there is also count, stop if none is met
  • Support byday, byweekday will alse recognized as byday. And positive and negative numbers are not recognized.
  • Support bymonth
  • Support bymonthday
  • Support byyearday
  • Support byweekno, However, this can cause performance problems. Also, it is mandatory to consider Monday as the beginning of the day
  • Bysetpos is not supported. This field may be useful if I implement FREQ=HOYRLY. Unfortunately, that didn't happen.

FREQ=WEEKLY

Same as FREQ=DAILY.It should be noted that bysetpos is still not supported here, although there may be several days a week to meet the conditions, but I do not understand the meaning of setting it.

FREQ=MONTHLY

Same as FREQ=DAILY.

FREQ=YEARLY

Same as FREQ=DAILY.

  • Support byday, byweekday will alse recognized as byday. Byday can contain only nth or no nth at the same time. Actually, I don't understand why. Don't it just get the dates and filter them ?

Need attention

  1. The default and maximum cut-off time is set to 2300 years and cannot be changed at this time.
  2. Because BYHOUR is not supported, the end time is compared by day. The logic will be modified later.
  3. Bysetpos is not supported.

API

RRuleSet.constructor

new rruleset with str.

const set = new JsRRuleSet(
  "DTSTART;TZID=America/New_York:20231126T091800Z\nRRULE:FREQ=MONTHLY;COUNT=3;WKST=MO"
);

RRUleSet.tz

set timezone. Overwrites the value in the string.

set.tz("Asia/Shanghai");

RRuleSet.set_dt_start

when use str like RRULE:FREQ=MONTHLY;COUNT=3;WKST=MO, without dt_start init rruleSet, You can call this function to set the start time. Overwrites the value in the string.

set.set_dt_start("20231129T105959");

RRuleSet.set_until

Set until separately. Overwrites the value in the string.

set.set_until("20231129T105959");

RRuleSet.set_count

Set count separately. Overwrites the value in the string.

set.set_count(10);

RRuleSet.between

Used to filter the list returned by the all function. This is useful if a lot of data is returned. Filter results will include the start and end of the day. You have to deal with scenarios that return empty.

set.between("20231106T091800Z", "20231130T091859Z");

RRuleSet.all

Returns all the occurrences of the rrule between dt_start and until. if set count, The maximum length of the return list is count, regardless of whether until is reached.

RRuleSet.valueOf

Return rrule string.

const data = {
  dtStart: "20221126T091800Z",
  count: 3,
  freq: "MONTHLY",
  interval: 2,
  until: "20231126T091800Z",
  wkst: "MO",
  tz: "America/New_York",
};
const set = getJsRRuleSet(JSON.stringify(data));
console.log(set2.valueOf());

// DTSTART;TZID=America/New_York:20221126T091800Z\nRRULE:FREQ=MONTHLY;COUNT=3;UNTIL=20231126T091800Z;INTERVAL=2;WKST=MO

Test

For different loops, as well as most of the various parameter combinations, I have made a comparison with rrule-js to ensure the correctness of the logic. You can view specific test cases in there.

License

This project is licensed under MIT License