Module: IB::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)


12
13
14
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
# File 'lib/ib/eod.rb', line 12

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