Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

use neri-schneider algorithm in calendar#10449

Merged
RaimoNiskanen merged 4 commits intoerlang:masterfrom
dkuku:use_neri-scheider_algorithm_in_calendar
Jan 14, 2026
Merged

use neri-schneider algorithm in calendar#10449
RaimoNiskanen merged 4 commits intoerlang:masterfrom
dkuku:use_neri-scheider_algorithm_in_calendar

Conversation

@dkuku
Copy link
Contributor

@dkuku dkuku commented Dec 7, 2025

This algorithm is O1 and it is over 2x faster than the current one.
I implemented it in elixir and this is the same logic. In the elixir pr the benchmarks are against elixir version of the current algorithm used in erlang.
It also works for negative dates which was not supported by the current algorithm, so the specs may need update but I keep it unchanged for now.

@CLAassistant
Copy link

CLAassistant commented Dec 7, 2025

CLA assistant check
All committers have signed the CLA.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 7, 2025

CT Test Results

β€‡β€ˆβ€‡β€‡2 filesβ€„β€ƒβ€‡β€ˆβ€‡97 suites   1h 7m 52s ⏱️
2β€ˆ238 tests 2β€ˆ187 βœ…β€ƒ51 πŸ’€β€ƒ0 ❌
2β€ˆ629 runsβ€Šβ€ƒ2β€ˆ573 βœ…β€ƒ56 πŸ’€β€ƒ0 ❌

Results for commit b53d236.

♻️ This comment has been updated with latest results.

To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass.

See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally.

Artifacts

// Erlang/OTP Github Action Bot

@IngelaAndin IngelaAndin added the team:VM Assigned to OTP team VM label Dec 8, 2025
@Maria-12648430
Copy link
Contributor

Interesting... 😺

That said, I see that there are already tests for the affected functions in place, but IMO they're not too conclusive, they only test symmetry, and even that looks a little dubious to me. Could you provide some more tests (unit/common and maybe also property tests) that check if the computed results are actually correct? πŸ€”

@dkuku
Copy link
Contributor Author

dkuku commented Dec 8, 2025

Interesting... 😺

That said, I see that there are already tests for the affected functions in place, but IMO they're not too conclusive, they only test symmetry, and even that looks a little dubious to me. Could you provide some more tests (unit/common and maybe also property tests) that check if the computed results are actually correct? πŸ€”

I did not check the existing tests, my bad. updated

@Maria-12648430
Copy link
Contributor

I will take a closer look at the tests themselves tomorrow, but for now, note that you have to insert calls for the proptests in calendar_prop_SUITE.erl for them to be run.

0 = calendar:date_to_gregorian_days(0, 1, 1),
{0, 1, 1} = calendar:gregorian_days_to_date(0),

%% Test year 0 boundaries (year 0 is a leap year)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that got me thinking πŸ€” Turns out there is no year 0 in the Gregorian calendar, year 1BC is immediately followed by year 1AD 🀯

And while the calendar module doc states that the Gregorian calendar of this module "is extended back to year 0", IMO this simply doesn't work out. There is no year 0 in the Gregorian calendar, period. Year 0, if you would instead assume the astronomical calendar, would map to year 1BC in the Gregorian calendar. In any case, this would mean that "year 0" (1BC) is not a leap year.

@IngelaAndin (and maybe also @bjorng), what are your thoughts about this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that is_leap_year(0) results in true, which considering what I said above would also be wrong?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe calling the current implementation gregorian is invalid because is uses astronomical and this is how it works currently:

 % iex 
Erlang/OTP 26 [erts-14.2.5] [source] [64-bit] [smp:14:14] [ds:14:14:10] [async-threads:1] [jit]

Interactive Elixir (1.16.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :calendar.gregorian_days_to_date(0)
{0, 1, 1}
iex(2)> :calendar.gregorian_days_to_date(1)
{0, 1, 2}
iex(3)> :calendar.gregorian_days_to_date(58)
{0, 2, 28}
iex(4)> :calendar.gregorian_days_to_date(59)
{0, 2, 29}
iex(5)> 

Copy link
Contributor

@Maria-12648430 Maria-12648430 Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I know... the current implementation is according to ISO 8601:200x, which tl;dr boils down to astronomical year numbering (which makes more sense/is more practical than the gregorian with its cumbersome 1BC/1AD transition), but calls it "gregorian extended to 0"; the "... extended to 0" part only occurs in the module doc, though, everywhere else it is simply called Gregorian. Now, fixing the documentation would be no big issue I think, but unfortunately the astronomical-vs-gregorian confusion goes down to the function names, too...

However, that is kinda outside the scope of this PR. As far as this PR goes, I'm all good =)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will leave this for discussion. it's an existing bug.
Maybe introducing an astronomical_days_to_date and deprecating the gregorian/1 would be a solution ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference this is called date_from_iso_days in elixir.
elixir-lang/elixir@904adda

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consulted with @juhlig, and after some research we concluded that the documentation is correct and matches the implementation, and vice versa. A question that arose however is why there is a restriction for non-negative years. Admittedly, it is rare that you have to deal with such dates, but why restrict it at all?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous implementation just did not support it - it required some tweaks.
I think this limitation can be removed - the algorithm supports negative dates just fine.
It is not a popular usecase probably - but I think it should be enabled even to allow solving riddles in erlang.
I can add tests for negative dates also. But it may be better to have a separate pr with the changes ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the OTP team to decide πŸ€·β€β™€οΈ But seeing that there are many functions to change to consistely allow for negative years, plus their tests, plus documentation modifications, personally I'd opt for a separate PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @bjorng probably has some insight and otherwise I think @rickard-green is our time expert.

@RaimoNiskanen
Copy link
Contributor

I think this PR looks fine, but I want to verify it thoroughly, and that will have to wait until after the holidays.

Regarding the Gregorian Year Zero question, I think the documentation of calendar should be updated to state the term "proleptic Gregorian calendar", which appears to be what it is called, and explain some more about that it is an extension of the same algorithm towards earlier in time that is useful although it does not correspond to any calendar that was in use back then.

I also see no problem in extending the calendar beyond year zero, since the new algorithm can handle that.

@RaimoNiskanen RaimoNiskanen self-assigned this Dec 19, 2025
@RaimoNiskanen RaimoNiskanen self-requested a review December 19, 2025 12:42
@dkuku
Copy link
Contributor Author

dkuku commented Dec 20, 2025

@RaimoNiskanen I made a pr for negative dates also that changes the docs. It builds on top of this pr.
I did it in a separate pr on purpose to keep the changes small
dkuku@918b6e4

@dkuku dkuku changed the title use neri-scheider algorithm in calendar use neri-schneider algorithm in calendar Jan 2, 2026
@RaimoNiskanen
Copy link
Contributor

I did it in a separate pr on purpose to keep the changes small

That is in a separate commit, not a separate PR, right.
Anyway, I think that change belongs in this PR, as a separate commit.

@RaimoNiskanen
Copy link
Contributor

... and I had some comments on your commit dkuku@918b6e4. I hope you can see them since I had a bit of bad luck with the GitHub Web interface, and had to refresh, change wiews, etc, to see them again ...

@RaimoNiskanen RaimoNiskanen force-pushed the use_neri-scheider_algorithm_in_calendar branch from 86d7c17 to b53d236 Compare January 14, 2026 13:04
@RaimoNiskanen
Copy link
Contributor

I squashed the test commits and added my clarification about the proleptic Gregorian calendar. When checks have completed I will merge this PR...

Copy link
Contributor

@RaimoNiskanen RaimoNiskanen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me!

@dkuku
Copy link
Contributor Author

dkuku commented Jan 14, 2026

Sorry @RaimoNiskanen, I saw your pr on friday and started replying but I got distracted and then was weekend :D
Thanks for picking it up.

@RaimoNiskanen RaimoNiskanen merged commit c0c661d into erlang:master Jan 14, 2026
23 of 24 checks passed
@RaimoNiskanen
Copy link
Contributor

Thank you for your pull request!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

team:VM Assigned to OTP team VM

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants