Skip to content

Conversation

@KristjanESPERANTO
Copy link
Collaborator

Motivation

The parseHoliday() function was ~180 lines long with complex nested logic for handling both public holidays (PH) and school holidays (SH). This refactoring improves readability by extracting reusable helper functions and simplifying the main parsing loop.

Changes

  • Extracted helper functions:
    • getDateNumber(month, day) - converts to comparable number
    • collectSHRangesForYear() - collects all SH ranges for a year
    • sortRangesByStartDate() - sorts ranges chronologically
    • createPublicHolidaySelector() - PH selector as standalone function
    • createSchoolHolidaySelector() - SH selector as standalone function
    • parseSingleHolidayToken() - handles single PH/SH token
  • Simplified parseHoliday(): Reduced from ~180 lines to ~30 lines
  • Improved comments: Consistent style with JSDoc and vim fold markers

Side effect

SH parsing is now robust against non-chronological data order (ranges are sorted before processing). This simplifies future migration to alternative data sources (e.g. OpenHolidays API), which I am currently exploring for #300.

Breaking Changes

None. Internal refactoring only.


Happy New Year! 🥳

Previously, the SH selector assumed holiday types were defined in
chronological order in the data files. If winter holidays (Dec-Jan)
were listed before spring holidays (Apr-May), dates in spring would
incorrectly return false.

Now all holiday ranges are collected first and sorted chronologically
before checking, making the code more robust against different data
orderings (e.g., if/when we switch to other sources like OpenHolidays API).
Extracted three helper functions to simplify the SH selector logic:
- getDateNumber(month, day): Convert month/day to comparable number
- collectSHRangesForYear(holidays, year): Collect all ranges from all holiday types
- sortRangesByStartDate(ranges): Sort ranges chronologically

This makes the code more readable and easier to maintain. The SH
selector now uses these helpers instead of inline calculations.
- Created createPublicHolidaySelector() to encapsulate PH selector logic
- Reduces parseHoliday complexity by 57 lines
- PH parsing now uses single function call instead of inline closure
- Created createSchoolHolidaySelector() to encapsulate SH selector logic
- Reduces parseHoliday complexity by ~80 lines
- SH parsing now uses single function call instead of inline closure
- Removed obsolete FIXME comment (from 2015, Issue opening-hours#75)
- Added clarifying comment: SH does not support move days by design
  (school holidays are date ranges, not single-day events like PH)
…loop

- Extract single holiday token parsing into dedicated helper function
- Replace for-loop with clearer while-loop in parseHoliday
- Explicit comma skipping makes control flow more obvious
- Reduce code duplication by using target_array variable

The helper function parseSingleHolidayToken handles PH/SH token parsing
and returns the new position, making the main loop simpler and easier to
understand. The while-loop eliminates the confusion of having 'at'
modified both in the loop header (at++) and in the loop body.
@KristjanESPERANTO
Copy link
Collaborator Author

Since the tests cover the area quite well and they are green, I'm merging this.

@KristjanESPERANTO KristjanESPERANTO merged commit 71f6745 into opening-hours:develop Jan 2, 2026
5 checks passed
@KristjanESPERANTO KristjanESPERANTO deleted the refactor branch January 2, 2026 23:32
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.

1 participant