-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
feat(Core/Events): Add dynamic holiday date calculator #24038
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
feat(Core/Events): Add dynamic holiday date calculator #24038
Conversation
Replaces static SQL-based holiday dates with dynamic C++ calculation. Holidays are now computed at runtime using: - Computus algorithm for Easter-based holidays (Noblegarden) - Nth weekday calculation for floating holidays (Pilgrim's Bounty) - Fixed dates for standard holidays Includes unit tests covering years 1900-2200. DB overrides still supported for custom servers.
5d19425 to
61eee6f
Compare
|
does this align with the entries in or even better could those entries be taken into account maybe |
|
it would be great if the calendar could actually reflect what |
|
also is this one of your AI generated fixes? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR introduces dynamic holiday date calculation to replace static SQL-based holiday dates. It adds a new HolidayDateCalculator utility class that computes holiday dates at runtime using mathematical algorithms (Computus for Easter, nth-weekday calculation for Thanksgiving-like holidays, and fixed dates for regular holidays). The system generates dates for the current year plus 10 future years at server startup, while preserving database override capabilities for custom servers.
Key Changes:
- New holiday date calculation system supporting three types: fixed dates, nth weekday of month, and Easter-relative dates
- Comprehensive unit test coverage spanning 301 years (1900-2200) with edge case validation
- Integration with existing
GameEventMgrthat generates dynamic dates while maintaining DB override compatibility
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 11 comments.
| File | Description |
|---|---|
HolidayDateCalculator.h |
Declares calculator class with Easter (Computus), nth-weekday, and fixed-date calculation methods; defines holiday rule structures and enums |
HolidayDateCalculator.cpp |
Implements Gregorian Computus algorithm for Easter, nth-weekday finder, date packing/unpacking for WoW's 2000-2031 format, and holiday rule configuration |
HolidayDateCalculatorTest.cpp |
Comprehensive test suite with 485 lines covering known Easter dates, weekday calculations, pack/unpack roundtrips, leap years, and century boundaries across 1900-2200 |
GameEventMgr.cpp |
Modified LoadHolidayDates() to generate 11 years of dynamic dates per holiday, then load DB overrides; preserves backward compatibility |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Use std::chrono with thread-safe localtime_r/localtime_s - Add const to applicable variables - Change Weekday to enum class - Add source reference for Computus algorithm - Add unit test for packed date year limitations
No currently it doesn't... I'll see what I can do today
I use AI to help me quite a bit yeah, but its more like don't trust and verify/read through exactly what I'm doing. It's why also I wanted the unit tests. |
|
darkmoon faires dates are already beeing calculated in the core via the dbc configuration, the dbc entry is linked in
|
|
After digging deeper into this, I want to clarify how the integration actually works: The dynamic dates DO feed into game_event timing - they're not independent systems. The loading order in World.cpp is:
SetHolidayEventTime() (line 1880) reads from holiday->Date[] to set gameEvent.Start. So when we populate Date[] dynamically, both the calendar AND the game event timing use the same calculated dates. HolidayDateCalculator The only thing "hardcoded" in C++ is the calculation rules (Easter algorithm, "4th Thursday of November" logic), not the dates themselves. The holiday_dates table still works as an override layer for custom servers or cultural differences. |
this PR doesn't change that. Darkmoon uses Looping=1 with a fixed occurence interval, which works because it recurs at regular intervals |
Implement Jean Meeus algorithm to calculate Chinese New Year dates dynamically using astronomical new moon calculation instead of a static lookup table. CNY falls on the new moon between Jan 21-Feb 20. - Add CalculateLunarNewYear() with full Meeus algorithm - Add DateToJulianDay/JulianDayToDate conversion functions - Add CalculateNewMoon() with 15 correction terms from Table 49.A - Update Lunar Festival rule to use LUNAR_NEW_YEAR calculation type - Add 5 unit tests covering years 1900-2200 with 100% accuracy
Add 7 additional fixed-date holidays to the dynamic system: - Midsummer Fire Festival (Jun 21) - Fireworks Spectacular (Jul 4) - Pirates' Day (Sep 19) - Brewfest (Sep 20) - Hallow's End (Oct 18) - Day of the Dead (Nov 1) - Winter Veil (Dec 15) Total holidays now managed by dynamic system: 13
- Alphabetize HolidayDateCalculator.h include - Use explicit time_point type instead of auto
|
I think maybe what I should do to tidy this up is likely just generate 3 years vs 10 (client limitation anyways) as well potentially have game_event.start_time be the override since it's human readable to begin with? Big question I have is should we rename to something like start_time_override to be more specific? And it should be that it's blank for the most part unless admins want to change those dates? EDIT: Refactored for these changes other than renaming sql |
- otherwise events would disappear right on their ending date after restart - also you can look very far back in the calendar
- Add all three Darkmoon Faire locations (374, 375, 376) to HolidayRules - Special handling in LoadHolidayDates() for multi-date holidays (4 per year) - Set Duration[0] = 168 hours (7 days) if not set in DBC - Use -2 day offset (Friday start for building phase before Sunday faire) - Add GetDarkmoonFaireDates dayOffset parameter for configurable offset - Add integration test verifying Darkmoon entries in HolidayRules
- Change from month % 3 (3 locations) to month % 2 (2 locations) - Odd months (Jan, Mar, May...) = Alliance Elwynn (374) - Even months (Feb, Apr, Jun...) = Horde Mulgore (375) - Remove Terokkar (376) as it's not used in WotLK
Updated CalculateHolidayDate() to use month % 2 instead of month % 3 for proper 2-location alternation (Elwynn odd months, Mulgore even months). Also updated unit tests to match the WotLK 2-location pattern.
Rotation: Mulgore (Jan/Apr/Jul/Oct) -> Terokkar (Feb/May/Aug/Nov) -> Elwynn (Mar/Jun/Sep/Dec) Uses month % 3 pattern for location offset calculation.
|
Wiki PR azerothcore/wiki#1153 |
…me_event - these also get calculated automatically now
|
tested again on the latest revision. dates in the in-game calendar look good to me for the last year and the upcoming year visible in the client |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 12 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Clamp years before 2000 to offset 0 to prevent integer underflow - Change per-date holiday logging from LOG_INFO to LOG_DEBUG - Fix Metonic cycle test comment to explain 30-day tolerance
Tests Apr 25, Apr 30, and Dec 31 edge cases where the calculated weekday may roll into the next month (or next year for Dec 31).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Changes Proposed:
Replaces static SQL-based holiday dates with dynamic C++ calculation, eliminating the need for recurring SQL maintenance as years progress.
The
game_event.start_timecolumn in the database serves as an override for calculated dates. Ifstart_timeis set to a date in the current year or later, it will be used instead of the dynamically calculated date. This allows custom servers to override specific holiday dates without modifying the code.This PR proposes changes to:
holiday_datestable - no longer needed).New Files
HolidayDateCalculator.h/.cpp- Utility class that calculates holiday dates at runtime:HolidayDateCalculatorTest.cpp- Unit tests covering years 1900-2200Modified Files
GameEventMgr.cpp- Generates dynamic dates on load, DB overrides preserved for custom serversHolidays Covered
Client Limitation
While the algorithm calculates dates for any year (validated 1900-2200), the WoW 3.3.5a client uses a 5-bit year offset field, limiting displayable dates to years 2000-2031.
Issues Addressed:
SOURCE:
The changes have been validated through:
Easter dates validated against known astronomical Easter tables. Thanksgiving dates validated against US calendar. Lunar New Year validated against astronomical sources. Equinox/solstice calculations use Jean Meeus algorithms.
Tests Performed:
This PR has been:
Unit tests pass:
How to Test the Changes:
HolidayDateCalculatorTestto verify calculationsstart_timeingame_eventKnown Issues and TODO List:
holiday_datestable removed (dates calculated dynamically)