Class: Fasti::Calendar
- Inherits:
-
Object
- Object
- Fasti::Calendar
- Defined in:
- lib/fasti/calendar.rb
Overview
Represents a calendar for a specific month and year with configurable start of week.
This class provides calendar structure functionality including calendar grid generation, day calculations, and formatting support. It handles different week start preferences (Sunday vs Monday) and integrates with country-specific holiday detection via the holidays gem.
Instance Attribute Summary collapse
- #country ⇒ Integer, Symbol readonly
- #month ⇒ Integer, Symbol readonly
- #start_of_week ⇒ Integer, Symbol readonly
- #year ⇒ Integer, Symbol readonly
Instance Method Summary collapse
-
#calendar_grid ⇒ Array<Array<Integer, nil>>
Generates a 2D grid representing the calendar layout.
-
#day_headers ⇒ Array<String>
Returns day abbreviations arranged according to start_of_week preference.
-
#days_in_month ⇒ Integer
Returns the number of days in the calendar month.
-
#first_day_of_month ⇒ Date
Returns the first day of the calendar month.
-
#first_day_wday ⇒ Integer
Returns the day of the week for the first day of the month.
-
#holiday?(day) ⇒ Boolean
Checks if a specific day in this calendar month is a holiday.
-
#initialize(year, month, country:, start_of_week: :sunday) ⇒ Calendar
constructor
Creates a new calendar instance.
-
#last_day_of_month ⇒ Date
Returns the last day of the calendar month.
-
#leading_empty_days ⇒ Integer
Calculates the number of empty cells needed before the first day.
-
#month_year_header ⇒ String
Returns a formatted month and year header string.
-
#to_date(day) ⇒ Date?
Converts a day number to a Date object for this calendar’s month/year.
Constructor Details
#initialize(year, month, country:, start_of_week: :sunday) ⇒ Calendar
Creates a new calendar instance.
53 54 55 56 57 58 59 60 61 62 |
# File 'lib/fasti/calendar.rb', line 53 def initialize(year, month, country:, start_of_week: :sunday) @year = year @month = month @start_of_week = start_of_week.to_sym @country = country @holidays_for_month = nil @calendar_transition = CalendarTransition.new(@country) validate_inputs end |
Instance Attribute Details
#country ⇒ Integer, Symbol (readonly)
30 31 32 |
# File 'lib/fasti/calendar.rb', line 30 def country @country end |
#month ⇒ Integer, Symbol (readonly)
30 31 32 |
# File 'lib/fasti/calendar.rb', line 30 def month @month end |
#start_of_week ⇒ Integer, Symbol (readonly)
30 31 32 |
# File 'lib/fasti/calendar.rb', line 30 def start_of_week @start_of_week end |
#year ⇒ Integer, Symbol (readonly)
30 31 32 |
# File 'lib/fasti/calendar.rb', line 30 def year @year end |
Instance Method Details
#calendar_grid ⇒ Array<Array<Integer, nil>>
Generates a 2D grid representing the calendar layout.
The grid is an array of weeks (rows), where each week is an array of 7 days. Days are represented as integers (1-31) or nil for empty cells. The grid respects the start_of_week preference.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/fasti/calendar.rb', line 138 def calendar_grid grid = [] current_row = [] # Add leading empty cells for days before month starts leading_empty_days.times do current_row << nil end # Add only existing days (skip gap days) for continuous display (1..days_in_month).each do |day| # Only add days that actually exist (not in transition gaps) next unless to_date(day) current_row << day # Start new row on end of week if current_row.length == 7 grid << current_row current_row = [] end # Skip gap days completely - they don't take up space in the grid end # Add trailing empty cells and final row if needed if current_row.any? current_row << nil while current_row.length < 7 grid << current_row end grid end |
#day_headers ⇒ Array<String>
Returns day abbreviations arranged according to start_of_week preference.
204 205 206 207 208 209 |
# File 'lib/fasti/calendar.rb', line 204 def day_headers # Rotate headers based on start of week start_wday = WEEK_DAYS.index(start_of_week) || 0 DAY_ABBREVS.rotate(start_wday) end |
#days_in_month ⇒ Integer
Returns the number of days in the calendar month.
71 72 73 |
# File 'lib/fasti/calendar.rb', line 71 def days_in_month Date.new(year, month, -1).day end |
#first_day_of_month ⇒ Date
Returns the first day of the calendar month.
82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/fasti/calendar.rb', line 82 def first_day_of_month @calendar_transition.create_date(year, month, 1) rescue ArgumentError # If day 1 is in a gap (very rare), try day 2, then 3, etc. (2..31).each do |day| return @calendar_transition.create_date(year, month, day) rescue ArgumentError next end # Fallback to standard Date if all fails Date.new(year, month, 1) end |
#first_day_wday ⇒ Integer
Returns the day of the week for the first day of the month.
121 122 123 |
# File 'lib/fasti/calendar.rb', line 121 def first_day_wday first_day_of_month.wday end |
#holiday?(day) ⇒ Boolean
Checks if a specific day in this calendar month is a holiday.
254 255 256 257 258 259 |
# File 'lib/fasti/calendar.rb', line 254 def holiday?(day) date = to_date(day) return false unless date holidays_for_month.key?(date) end |
#last_day_of_month ⇒ Date
Returns the last day of the calendar month.
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/fasti/calendar.rb', line 102 def last_day_of_month # Start from the theoretical last day and work backwards max_days = Date.new(year, month, -1).day max_days.downto(1).each do |day| return @calendar_transition.create_date(year, month, day) rescue ArgumentError next end # Fallback to standard Date if all fails Date.new(year, month, -1) end |
#leading_empty_days ⇒ Integer
Calculates the number of empty cells needed before the first day.
This accounts for the start_of_week preference to properly align the first day of the month in the calendar grid.
182 183 184 185 186 187 |
# File 'lib/fasti/calendar.rb', line 182 def leading_empty_days # Calculate offset based on start of week preference start_wday = WEEK_DAYS.index(start_of_week) || 0 (first_day_wday - start_wday) % 7 end |
#month_year_header ⇒ String
Returns a formatted month and year header string.
218 219 220 221 |
# File 'lib/fasti/calendar.rb', line 218 def month_year_header date = first_day_of_month date.strftime("%B %Y") end |
#to_date(day) ⇒ Date?
Converts a day number to a Date object for this calendar’s month/year.
232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/fasti/calendar.rb', line 232 def to_date(day) return nil unless day return nil unless (1..days_in_month).cover?(day) begin @calendar_transition.create_date(year, month, day) rescue ArgumentError # Date falls in calendar transition gap (non-existent) nil end end |