How Woovi handles complex date generation with Javascript
Tags: programming, javascript
Published: 2023-03-27 13:20:41

Everyone comments that data in javascript is a nightmare. Whether to generate new dates, deal with existing dates, migrations, etc.
Regardless of the context, people go crazy with dates.

Within Woovi we have several products that work directly linked to a date.

We have the generation of a Pix, the recurrence of signatures, pix in installments, sending scheduled emails, scheduled payments, among others.

Today we're going to talk about how we calculate the space between two dates and the days they repeat: recurrence.

Let's imagine the following scenario:

## Scenario
Given a value, from 1 to 12, we want to generate the dates in that range based on a frequency. The frequency will be monthly and the dates must be generated on the same day as the initial one.

The initial date will always be the one when the script was run.

### Problems
- if the starting date is at the end of the month, we want you to take the closest previous day. If it's 31 today and the next one doesn't exist, you should get 30
- the same rule applies for February ending on the 28th
- the same rule applies for February in leap years

With pure javascript it is possible to do this generation. However, it can become somewhat difficult to guarantee that the rule is always correct.

What if we used something ready and that works?

So we decided to go with [RRule](https://github.com/jakubroztocil/rrule), which as the lib itself says:

"rrule.js supports recurrence rules as defined in the iCalendar RFC, with a few important differences. It is a partial port of the rrule module from the excellent python-dateutil library. On top of that, it supports parsing and serialization of recurrence rules from and to natural language."

## The Code
```ts
import { RRule } from 'rrule';

const recurrentNumber = 4;

const dateStart = moment(new Date())
  .startOf('day')
  .toDate();

const dateEnd = moment(dateStart)
  .add(recurrentNumber, 'month')
  .endOf('day')
  .toDate();

const rule = new RRule({
  freq: RRule.MONTHLY,
  dtstart: dateStart,
  until: dateEnd,
  bymonthday: -1,
```

Breaking in steps:
- declare the start date
- get the end date and add the number of months based in the recurrent number
```ts
const dateStart = moment(new Date())
  .startOf('day')
  .toDate();

const dateEnd = moment(dateStart)
  .add(recurrentNumber, 'month')
  .endOf('day')
  .toDate();
```
- then, we call the rrule
- pass the frequency, dtstart, until and the bymonthday which means:
```
If given, it must be either an integer, or an array of integers, meaning the month days to apply the recurrence to.
```
and the result having a date start for 01/31/2023 is:

```ts
// date start and date end
{
  dateStart: 2023-01-30T03:00:00.000Z,
  dateEnd: 2023-05-31T02:59:59.999Z
}
// array of generated date
[
  2023-01-31T03:00:00.000Z,
  2023-02-28T03:00:00.000Z,
  2023-03-31T03:00:00.000Z,
  2023-04-30T03:00:00.000Z
]
```

## Conclusion
There is a world of endless implementations for the above problem and code, but with Woovi you have just learned a new way that is simple and fun!

## References
- [RRule](https://github.com/jakubroztocil/rrule)

---

If you want to work in a startup in its early stages, This  is your chance. [Apply today!](https://woovi.com/jobs/)

---

[Woovi](https://woovi.com/) is a Startup that enables shoppers to pay as they please. To make this possible, Woovi provides instant payment solutions for merchants to accept orders.

---
Photo by <a href="https://unsplash.com/@insungyoon?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">insung yoon</a> na <a href="https://unsplash.com/pt-br/fotografias/w2JtIQQXoRU?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>