Module: IB::Eod::BuisinesDays

Defined in:
lib/ib/eod.rb

Class Method Summary collapse

Class Method Details

.business_days_between(start_date, end_date) ⇒ Fixnum

Calculates the number of business days in range (start_date, end_date]

Parameters:

  • start_date (Date)
  • end_date (Date)

Returns:

  • (Fixnum)


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/ib/eod.rb', line 15

def self.business_days_between(start_date, end_date)
	days_between = (end_date - start_date).to_i
	return 0 unless days_between > 0

              # Assuming we need to calculate days from 9th to 25th, 10-23 are covered
              # by whole weeks, and 24-25 are extra days.
              #
              # Su Mo Tu We Th Fr Sa    # Su Mo Tu We Th Fr Sa
              #        1  2  3  4  5    #        1  2  3  4  5
              #  6  7  8  9 10 11 12    #  6  7  8  9 ww ww ww
              # 13 14 15 16 17 18 19    # ww ww ww ww ww ww ww
              # 20 21 22 23 24 25 26    # ww ww ww ww ed ed 26
              # 27 28 29 30 31          # 27 28 29 30 31
                  whole_weeks, extra_days = days_between.divmod(7)

                  unless extra_days.zero?
              # Extra days start from the week day next to start_day,
              # and end on end_date's week date. The position of the
              # start date in a week can be either before (the left calendar)
              # or after (the right one) the end date.
              #
              # Su Mo Tu We Th Fr Sa    # Su Mo Tu We Th Fr Sa
              #        1  2  3  4  5    #        1  2  3  4  5
              #  6  7  8  9 10 11 12    #  6  7  8  9 10 11 12
              # ## ## ## ## 17 18 19    # 13 14 15 16 ## ## ##
              # 20 21 22 23 24 25 26    # ## 21 22 23 24 25 26
              # 27 28 29 30 31          # 27 28 29 30 31
              #
              # If some of the extra_days fall on a weekend, they need to be subtracted.
              # In the first case only corner days can be days off,
              # and in the second case there are indeed two such days.
                    extra_days -= if start_date.tomorrow.wday <= end_date.wday
                                    [start_date.tomorrow.sunday?, end_date.saturday?].count(true)
                                  else
                                    2
                                  end
                  end

                  (whole_weeks * 5) + extra_days
end