Thumbnail

Managing Recurring Events in Node.js with rrule

· 4 min read

Recurring events are a common feature in apps like calendars, task managers, and scheduling systems. However, implementing this functionality can get complicated, especially when users want events to repeat at different frequencies, on specific days, or for a limited number of times. The rrule library is a powerful tool that makes managing recurring events simple and reliable.

In this article, we’ll show you how to use the rrule library in Node.js to handle recurring events, convert them into plain text for users, and store them in a database for long-term use.

Why Use rrule?

Imagine you’re building a feature where users can set up events that repeat:

  • Daily, weekly, or monthly
  • On specific days of the week (e.g., Monday, Wednesday, Friday)
  • A certain number of times or until a specific date

Coding all of this manually can lead to complex and error-prone logic. The rrule library simplifies everything by letting you define recurrence rules with just a few lines of code.

Getting Started with rrule

Before we begin, install the required libraries:

npm install rrule moment-timezone
  • rrule: Helps generate and handle recurring event rules.
  • moment-timezone: Ensures events are time-zone-aware, especially useful for global applications.

Creating Recurring Events

Here’s how you can define a recurring event using rrule:

const { RRule } = require('rrule');
const moment = require('moment-timezone');

// Function to create an RRule
const createRRule = (input) => {
  return new RRule({
    freq: input.repeatEveryUnit === 'day'
      ? RRule.DAILY
      : input.repeatEveryUnit === 'week'
      ? RRule.WEEKLY
      : RRule.MONTHLY,
    interval: input.repeatEvery, // How often it repeats
    count: input.endType === 'after' ? input.occurrences : null, // Number of times it repeats
    until: input.endType === 'on' ? moment(input.endDate).toDate() : null, // End date
    dtstart: moment(input.startDate).toDate(), // Start date
    byweekday: input.repeatOn ? input.repeatOn.map(day => RRule[day.toUpperCase()]) : null, // Days of the week
  });
};

// Example input
const input = {
  repeatEveryUnit: 'week', // Repeat weekly
  repeatEvery: 1, // Every 1 week
  endType: 'after', // End after 10 occurrences
  occurrences: 10,
  startDate: '2023-05-15T10:00:00', // Start date
  endDate: null, // Not used since we’re ending after 10 times
  repeatOn: ['mo', 'we', 'fr'], // Monday, Wednesday, Friday
};

// Create the rule
const rule = createRRule(input);

// Output the rule as a string
console.log(rule.toString());

How It Works

  • freq: Specifies how often the event repeats (daily, weekly, or monthly).
  • interval: Sets the gap between recurrences.
  • count: Limits the number of occurrences (e.g., 10 times).
  • until: Specifies an end date for the recurrence.
  • byweekday: Specifies days of the week for the recurrence (e.g., Monday, Wednesday, Friday).

In this example, the rule defines a recurring event that happens every week on Monday, Wednesday, and Friday, starting on May 15, 2023, and repeats 10 times.

Making Rules User-Friendly

While the rule works perfectly for computers, users need to see it in plain English. The rrule library provides a method to convert rules into readable text:

const readableText = (rule) => rule.toText();

console.log(readableText(rule));


For the above example, this will generate:

"Repeats every week on Monday, Wednesday, and Friday 10 times"

This is great for displaying the recurrence details to users in a simple format.

Storing Recurring Rules in a Database

Once you’ve created a recurring rule, you’ll likely need to save it in a database so it can be retrieved later. The rrule library makes this easy by letting you store the rule as a string.

Here’s how to save and retrieve recurring rules using a PostgreSQL database and MikroORM.

Step 1: Define the Database Table (Entity)

We’ll define an Event entity where we store the rule:

import { Entity, PrimaryKey, Property } from 'mikro-orm';

@Entity()
export class Event {
  @PrimaryKey()
  id!: number; // Unique identifier for the event

  @Property({ type: 'text' })
  name!: string; // Name or title of the event

  @Property({ type: 'text' })
  rrule!: string; // Recurrence rule stored as a string
}


Step 2: Save the Rule in the Database

Here’s how you can generate a rule, serialize it, and save it:

const { MikroORM } = require('@mikro-orm/core');
const { Event } = require('./entities/Event');

const orm = await MikroORM.init({
  entities: [Event],
  dbName: 'my_database',
  type: 'postgresql',
});

const em = orm.em.fork();

const input = {
  repeatEveryUnit: 'week',
  repeatEvery: 1,
  endType: 'after',
  occurrences: 10,
  startDate: '2023-05-15T10:00:00',
  endDate: null,
  repeatOn: ['mo', 'we', 'fr'],
};

const rule = createRRule(input);

const event = new Event();
event.name = 'Weekly Team Meeting';
event.rrule = rule.toString();

await em.persistAndFlush(event);

Step 3: Retrieve and Use the Rule

When you need the recurring rule later, you can fetch it from the database and rebuild it:

const savedEvent = await em.findOne(Event, { id: 1 });

if (savedEvent) {
  const rule = RRule.fromString(savedEvent.rrule);
  console.log(rule.toText()); // Display the rule in plain text
}

This makes it easy to manage recurring events in your application while keeping the database clean and efficient.

Wrapping Up

The rrule library takes the hassle out of managing recurring events. It provides a clean way to define recurrence patterns, make them human-readable, and save them for later use. With this approach, you can confidently build powerful scheduling features into your applications.

We specialize in creating complex custom software solutions. If you’re looking for expert development services, feel free to reach out to us!

Boopesh Mahendran

About Boopesh Mahendran

Boopesh is one of the Co-Founders of CyberMind Works and the Head of Engineering. An alum of Madras Institute of Technology with a rich professional background, he has previously worked at Adobe and Amazon. His expertise drives the innovative solutions at CyberMind Works.

Man with headphones

CONTACT US

How can we at CMW help?

Want to build something like this for yourself? Reach out to us!

Link copied
Copyright © 2025 CyberMind Works. All rights reserved.