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

Regression: Duration.normalize() not working properly after 3.4.1 #1493

Closed
thomassth opened this issue Aug 24, 2023 · 8 comments · Fixed by #1494
Closed

Regression: Duration.normalize() not working properly after 3.4.1 #1493

thomassth opened this issue Aug 24, 2023 · 8 comments · Fixed by #1494

Comments

@thomassth
Copy link
Contributor

thomassth commented Aug 24, 2023

Describe the bug
See https://github.com/moment/luxon/actions/runs/5943754818/job/16119553727

- Expected  - 2
+ Received  + 2

  Object {
-   "days": 363,
-   "years": 1,
+   "days": -2,
+   "years": 2,
  }

- Expected  - 2
+ Received  + 2

  Object {
-   "days": 2,
-   "months": 0,
+   "days": -28,
+   "months": 1,
  }

Likely the fix for #1482 in 3.4.1 (11e454c) broke #1467

To Reproduce
Duration.fromObject({ hours: 96, minutes: 0, seconds: -10 }).normalize().toObject())
should equal { hours: 95, minutes: 59, seconds: 50} but no conversion happened.

Actual vs Expected behavior
All tests should be passing

@tonysamperi
Copy link

Exactly, just wanted to report the same! I discovered it while updating my ts-luxon.
I don't mean to be rude, but what's the point of having tests if you don't run them before publishing?
Anyway I can try to figure out a way to make both

"Duration#normalize rebalances negative units"
and the newer
"Duration#shiftTo handles mixed units"

if you confirm that both can pass at the same time.

Cheers

image

@thomassth
Copy link
Contributor Author

In a way we can just run rescale() before every normalize(), since rescale never had any problem on conversion

But that feels wrong

@tonysamperi
Copy link

@thomassth no we can't rescale, because rescale calls normalize 😅

@diesieben07
Copy link
Collaborator

I apologize for the broken release again.
I'm currently sitting down with pen and paper to revise the normalization algorithm once and for all. It has caused nothing but trouble in the past, resulting in numerous issues like this.

@tonysamperi
Copy link

@diesieben07 is there an analysis of all the use cases the algorythm should cover?
Because I'm really intrigued by the problem...yesterday I spent several hours, but when I solved one, I broke another.
Also I'm having trouble to understand if the problem are negative units, or adjustments that happen between distant units (e.g year / day) which have then a very small raw value...

@diesieben07
Copy link
Collaborator

Here is (as far as I see it) what normalize should do (assuming the overall value of the duration is positive):

  • Remove excessive "lower order" values, by converting them to higher order units, e.g. { years: 2, days: 400 } becomes { years: 3, days: 35 }
  • Remove negative "lower order" values, by reducing a higher order unit to make the lower order positive, e.g. { years: 2, days: -2 } becomes { years: 1, days: 363 }.

The previous implementations never really made this distinction clear and attempted to handle both cases in unison.
I have now implemented two code paths, one for each case. All tests now pass, but I am going to investigate further if all cases are covered by the current test suite before committing to a pull request.

As for units which are overall negative in value, they are handled the same way, except that every step is inverted. For example { years: -2, days: 2 } becomes { years: -1, days: -363 }.

@tonysamperi
Copy link

Ok that makes sense. And I saw in the code the handling of overall negative values, managed with a double negate. That should be fine as long as the 2 cases above are handled correctly.

@diesieben07
Copy link
Collaborator

And I saw in the code the handling of overall negative values, managed with a double negate.

Correct. Although I have improved this now, removing the need for multiple intermediate objects.

brboi added a commit to odoo-dev/odoo that referenced this issue Aug 30, 2023
**Changelog**

**3.4.2 (2023-08-26)**

- Fixes regression from 3.4.1 (moment/luxon#1493)

**3.4.1 (2023-08-23)**

- Fixes for regressions from 3.4.0
  (moment/luxon#1482 and moment/luxon#1488)

**3.4.0 (2023-08-08)**

- Fix type checking on input zones
- Fix Islamic months listing
- Fix normalize() for negative inputs

**3.3.0 (2023-03-03)**

- Fix off-by-one in Interval#count (moment/luxon#1308)
- Support formatting for custom zones (moment/luxon#1377)
- Fix parsing for narrow spaces (moment/luxon#1369)
- Handle leap year issue with AD 100 (moment/luxon#1390)
- Allow parsing of just an offset

**3.2.1 (2023-01-04)**

- Fix for RFC-2822 regex vulnerability
- Better handling of BCP tags with -x- extensions

**3.2.0 (2022-12-29)**

- Allow timeZone to be specified as an intl option
- Fix for diff's handling of end-of-month when crossing leap years
  (moment/luxon#1340)
- Add Interval.toLocaleString() (moment/luxon#1320)

**3.1.1 (2022-11-28)**

- Add Settings.twoDigitCutoffYear

**3.1.0 (2022-10-31)**

- Add Duration.rescale

**3.0.4 (2022-09-24)**

- Fix quarters in diffs (moment/luxon#1279)
- Export package.json in package (moment/luxon#1239)

**3.0.2 (2022-08-28)**

- Lots of doc changes
- Added DateTime.expandFormat
- Added support for custom conversion matrices in Durations
robodoo pushed a commit to odoo/odoo that referenced this issue Sep 4, 2023
**Changelog**

**3.4.2 (2023-08-26)**

- Fixes regression from 3.4.1 (moment/luxon#1493)

**3.4.1 (2023-08-23)**

- Fixes for regressions from 3.4.0
  (moment/luxon#1482 and moment/luxon#1488)

**3.4.0 (2023-08-08)**

- Fix type checking on input zones
- Fix Islamic months listing
- Fix normalize() for negative inputs

**3.3.0 (2023-03-03)**

- Fix off-by-one in Interval#count (moment/luxon#1308)
- Support formatting for custom zones (moment/luxon#1377)
- Fix parsing for narrow spaces (moment/luxon#1369)
- Handle leap year issue with AD 100 (moment/luxon#1390)
- Allow parsing of just an offset

**3.2.1 (2023-01-04)**

- Fix for RFC-2822 regex vulnerability
- Better handling of BCP tags with -x- extensions

**3.2.0 (2022-12-29)**

- Allow timeZone to be specified as an intl option
- Fix for diff's handling of end-of-month when crossing leap years
  (moment/luxon#1340)
- Add Interval.toLocaleString() (moment/luxon#1320)

**3.1.1 (2022-11-28)**

- Add Settings.twoDigitCutoffYear

**3.1.0 (2022-10-31)**

- Add Duration.rescale

**3.0.4 (2022-09-24)**

- Fix quarters in diffs (moment/luxon#1279)
- Export package.json in package (moment/luxon#1239)

**3.0.2 (2022-08-28)**

- Lots of doc changes
- Added DateTime.expandFormat
- Added support for custom conversion matrices in Durations

closes #133599

Related: odoo/enterprise#46556
Signed-off-by: Luca Vitali (luvi) <luvi@odoo.com>
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 a pull request may close this issue.

3 participants