Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subtracting a day from a first day of month date results in subtracting one year and one day. #222

Closed
cezarcarvalhaes opened this issue Feb 1, 2022 · 3 comments · Fixed by #223
Labels

Comments

@cezarcarvalhaes
Copy link
Contributor

This is very edge-case issue, but came across it today, as it's the first of the month.

Essentially, if a creating a new date using $dateFromParts, and inside that expression you also subtract a day, the result ends up being a year and a day before its input. This only happens for dates that are the first of the month (eg. '02/01/2022'). Other dates work as expected. This same behavior is not replicated in mongo playground.

I made a quick sample repo demonstrating the issue.

Here's the Aggregator script as well:

[
    {
    $addFields: {
      parsedDate: {
        $dateFromString: {
          dateString: "$date",
          format: "%m/%d/%Y",
        },
      }
    },
  },
  {
    $addFields: {
      newDate: {
          $dateFromParts: {
          year: {
            $year: "$parsedDate",
          },
          month: {
            $month: "$parsedDate",
          },
          day: {
            $subtract: [
              {
                $dayOfMonth: "$parsedDate",
              },
              1,
            ],
          },
        },
      },
    },
  },
  {
    $project: {
      value: {
              $dateToString: {
                date: '$newDate',
                format: '%m/%d/%Y',
              },
            },
    },
  },
]

If you pass the script above { date: '02/01/2022' }, the result will be 01/31/2021 when it should be 01/31/2022. If you pass it 02/02/2022 it returns 02/01/2022.

We tested this in versions 6.0, 5.1, 5.0, and 4.4 and all got the same results.

@kofrasa kofrasa added the bug label Feb 1, 2022
@kofrasa
Copy link
Owner

kofrasa commented Feb 2, 2022

Verified at https://runkit.com/embed/bema0uvqcwvn

I do accept PRs if you want to give this a stab.

@kofrasa
Copy link
Owner

kofrasa commented Feb 2, 2022

Some useful places to look.

minimum value for day of month is 1
https://github.com/kofrasa/mingo/blob/master/src/operators/expression/date/_internal.ts#L73

subtracting 1 from the day causes it to be 0 which is less than the expected min for the day unit. this carries a remainder to adjust the next unit.
https://github.com/kofrasa/mingo/blob/master/src/operators/expression/date/dateFromParts.ts#L59-L63

remainder is correctly updated from day->month but is not reset for the next unit transition month -> year. An else block after L68 that resets remainder should fix it since it must not carry over to the next unit when we don't take either of the above paths.

This is just from code analysis and has not been verified yet. Looking forward to your PR and thanks again for catching this.

@kofrasa
Copy link
Owner

kofrasa commented Feb 2, 2022

Perfect you already caught it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants