Skip to content

fix(#114): don't lose the day of a date that is set in the datetime helper - #188

Open
muditagrawal2007 wants to merge 1 commit into
joplin:masterfrom
muditagrawal2007:fix/114-datetime-set-date-overflow
Open

muditagrawal2007 wants to merge 1 commit into
joplin:masterfrom
muditagrawal2007:fix/114-datetime-set-date-overflow

Conversation

@muditagrawal2007

Copy link
Copy Markdown

Fixes #114

The bug

The datetime helper builds the date it is given by setting the day, the month and the year one after the other on the current date:

now.set("date", parsedDate.date);
now.set("month", parsedDate.month);
now.set("year", parsedDate.year);

Setting the day first overflows into the next month when the current month is shorter than the day that was asked for, and the day is then silently lost. November has 30 days, so the 31st of December became the 1st of December, and every date calculated from it was 30 days off.

The dates in the report are exactly what this produced on 30 November 2025:

Date Expected Reported
Mid-Project Review (deadline − 14 days) 17/12/2025 17/11/2025
Project Closure (deadline + 7 days) 07/01/2026 08/12/2025

The bug only shows up while the current month is shorter than the day that is set, which is why it can go unnoticed for months at a time.

Before / after

A deadline of the 31st of December 2025, with the note created on the 30th of November 2025:

Before the fix

After the fix the dates are calculated from the deadline that was entered:

After the fix

Both images are rendered from the real production code, with the DD/MM/YYYY date format.

The fix

src/helpers/datetime.ts

The day is set to 1 before the month and the year are changed, and the day that was asked for is set last:

now.set("date", 1);
now.set("year", parsedDate.year);
now.set("month", parsedDate.month);
now.set("date", parsedDate.date);

With the day at 1, changing the month or the year can't overflow, and setting the day last can't overflow either, because the date that is parsed always exists in the month it belongs to.

src/utils/dateAndTime.ts

Documented that parseDate() returns a zero based month, the way moment handles it, so that the result can be passed to moment's set("month", ...) directly. No behaviour change.

Tests

tests/helpers/datetime.spec.ts is a new file with tests for the datetime helper, including the reported case and a template that calculates its dates from a deadline.

Against the old implementation 11 of the 13 new tests fail:

✕ should keep the day of the date that was set (#114)
✕ should keep the day of the date that was set when the month changes (#114)
✕ should keep the day of the date that was set when the year changes (#114)
✕ should keep the day of the date that was set in February (#114)
✕ should calculate a date after the date that was set (#114)
✕ should calculate a date before the date that was set (#114)
✕ should calculate a month after the date that was set (#114)
✕ should calculate a year after the date that was set (#114)
✕ should keep the day of the date that was set together with a time (#114)
✕ should keep a leap day (#114)
✕ should calculate the dates of a template from its deadline (#114)

The other two are guards for the cases that already worked.

Testing

  1. npm test — 114 tests pass.
  2. npm run lint — no new warnings.
  3. npm run dist — the plugin builds.
  4. In the app: follow the "Advanced date calculations" part of DEMO_TEMPLATE.md, enter a deadline at the end of a month and check that the calculated dates are 14 days before and 7 days after it.

…time helper

The datetime helper built the date it was given by setting the day, the
month and the year one after the other on the current date:

    now.set("date", parsedDate.date);
    now.set("month", parsedDate.month);
    now.set("year", parsedDate.year);

Setting the day first overflows into the next month when the current month
is shorter than the day that was asked for, and the day is then silently
lost. The 31st of December set while the current month is November became
the 1st of December, and every date calculated from it was 30 days off.

The user reported a deadline of 31/12/2025 producing a mid project review
of 17/11/2025 and a project closure of 08/12/2025, which is exactly what
this produced on 30 November 2025.

src/helpers/datetime.ts
- Set the day to 1 before changing the month and the year, and set the
  day last, so that the date that was asked for is kept.

src/utils/dateAndTime.ts
- Documented that parseDate() returns a zero based month, the way moment
  handles it.

tests/helpers/datetime.spec.ts
- Added tests for the datetime helper, including the reported case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Roblems with date time and calculation when set to 25-12-31

1 participant