holidays / holidays

A collection of Ruby methods to deal with statutory and other holidays. You deserve a holiday!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to prevent stacked observed holidays

kyrofa opened this issue · comments

This is more of a question than a bug report, I hope that's okay (feel free to direct me elsewhere if necessary).

I'm using this excellent gem to help with tracking holidays and PTO at work, and I'm struggling with groups of potentially observed holidays. Take Christmas, for example. At work, we get Christmas Eve, Christmas Day, and the day after Christmas off. I naively threw this together, then:

# [...]
months:
  # [...]
  12:
  #[...]
  - name: Christmas Eve
    regions: [work]
    mday: 24
    observed: to_weekday_if_weekend(date)
  - name: Christmas Day
    regions: [work]
    mday: 25
    observed: to_weekday_if_weekend(date)
  - name: Day after Christmas
    regions: [work]
    mday: 26
    observed: to_weekday_if_weekend(date)
# [...]

That's not quite what I want, though. Say Christmas Day fell on a Sunday, like it does this year. That ^ logic would have Christmas Day (observed) and Day after Christmas (observed) land on the same day, the 26th. I'd like it to push Christmas Day (observed) to Monday, but Day after Christmas (observed) to Tuesday. How would I best go about something like this? Is a custom method the only way?

Alright this works the way I want it to, but it doesn't please me as much as I would like to be pleased:

# [...]
months:
  # [...]
  12:
  # [...]
  - name: Christmas Eve
    regions: [work]
    mday: 24
    observed: christmas_eve_observed(date)
  - name: Christmas Day
    regions: [work]
    mday: 25
    observed: to_weekday_if_weekend(date)
  - name: Day after Christmas
    regions: [work]
    mday: 26
    observed: day_after_christmas_observed(date)

methods:
  christmas_eve_observed:
    arguments: date
    ruby: |
      christmas = Holidays::Factory::DateCalculator.weekend_modifier.to_weekday_if_weekend(Date.new(date.year, 12, 25))
      christmas_eve = christmas-1

      # If on a weekend, move to the preceding Friday
      if christmas_eve.wday == 0
        christmas_eve -= 2
      elsif christmas_eve.wday == 6
        christmas_eve -= 1
      end

      christmas_eve

  day_after_christmas_observed:
    arguments: date
    ruby: |
      christmas = Holidays::Factory::DateCalculator.weekend_modifier.to_weekday_if_weekend(Date.new(date.year, 12, 25))
      Holidays::Factory::DateCalculator.weekend_modifier.to_monday_if_weekend(christmas+1)

The issues I have with this approach:

  1. Methods can't call each other, so instead of making a christmas_observed method, for example, the christmas_eve_observed and day_after_christmas_observed methods both need to know how to calculate the observed Christmas date, which would ideally be an implementation detail and leads to duplication.
  2. It seems that methods being used for observed must take a date, which doesn't seem to be documented anywhere. All I need for these is a year.

Anyone know a way around these? Or any other way to make this cleaner?