Class: Time

Inherits:
Object
  • Object
show all
Defined in:
lib/business_time/core_ext/time.rb,
lib/business_time/core_ext/time.rb

Overview

Add workday and weekday concepts to the Time class

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.after_business_hours?(time) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/business_time/core_ext/time.rb', line 41

def after_business_hours?(time)
  time > end_of_workday(time)
end

.before_business_hours?(time) ⇒ Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/business_time/core_ext/time.rb', line 37

def before_business_hours?(time)
  time < beginning_of_workday(time)
end

.beginning_of_workday(day) ⇒ Object

Gives the time at the beginning of the workday, assuming that this time falls on a workday. Note: It pretends that this day is a workday whether or not it really is a workday.



19
20
21
22
23
# File 'lib/business_time/core_ext/time.rb', line 19

def beginning_of_workday(day)
  format = "%B %d %Y #{BusinessTime::Config.beginning_of_workday}"
  Time.zone ? Time.zone.parse(day.strftime(format)) :
      Time.parse(day.strftime(format))
end

.end_of_workday(day) ⇒ Object

Gives the time at the end of the workday, assuming that this time falls on a workday. Note: It pretends that this day is a workday whether or not it really is a workday.



9
10
11
12
13
# File 'lib/business_time/core_ext/time.rb', line 9

def end_of_workday(day)
  format = "%B %d %Y #{BusinessTime::Config.end_of_workday}"
  Time.zone ? Time.zone.parse(day.strftime(format)) :
      Time.parse(day.strftime(format))
end

.roll_backward(time) ⇒ Object

Rolls backwards to the previous end_of_workday when the time is outside of business hours



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/business_time/core_ext/time.rb', line 66

def roll_backward(time)
  if (Time.before_business_hours?(time) || !Time.workday?(time))
    prev_business_time = Time.end_of_workday(time) - 1.day
  elsif Time.after_business_hours?(time)
    prev_business_time = Time.end_of_workday(time)
  else
    prev_business_time = time.clone
  end

  while !Time.workday?(prev_business_time)
    prev_business_time -= 1.day
  end

  prev_business_time
end

.roll_forward(time) ⇒ Object

Rolls forward to the next beginning_of_workday when the time is outside of business hours



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/business_time/core_ext/time.rb', line 47

def roll_forward(time)

  if (Time.before_business_hours?(time) || !Time.workday?(time))
    next_business_time = Time.beginning_of_workday(time)
  elsif Time.after_business_hours?(time)
    next_business_time = Time.beginning_of_workday(time) + 1.day
  else
    next_business_time = time.clone
  end

  while !Time.workday?(next_business_time)
    next_business_time += 1.day
  end

  next_business_time
end

.weekday?(day) ⇒ Boolean

True if this time falls on a weekday.

Returns:

  • (Boolean)


33
34
35
# File 'lib/business_time/core_ext/time.rb', line 33

def weekday?(day)
  BusinessTime::Config.weekdays.include? day.wday
end

.workday?(day) ⇒ Boolean

True if this time is on a workday (between 00:00:00 and 23:59:59), even if this time falls outside of normal business hours.

Returns:

  • (Boolean)


27
28
29
30
# File 'lib/business_time/core_ext/time.rb', line 27

def workday?(day)
  Time.weekday?(day) &&
      !BusinessTime::Config.holidays.include?(day.to_date)
end

Instance Method Details

#business_time_until(to_time) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/business_time/core_ext/time.rb', line 87

def business_time_until(to_time)

  # Make sure that we will calculate time from A to B "clockwise"
  direction = 1
  if self < to_time
    time_a = self
    time_b = to_time
  else
    time_a = to_time
    time_b = self
    direction = -1
  end

  # Align both times to the closest business hours
  time_a = Time::roll_forward(time_a)
  time_b = Time::roll_forward(time_b)

  # If same date, then calculate difference straight forward
  if time_a.to_date == time_b.to_date
    result = time_b - time_a
    return result *= direction
  end

  # Both times are in different dates
  result = Time.parse(time_a.strftime('%Y-%m-%d ') + BusinessTime::Config.end_of_workday) - time_a   # First day
  result += time_b - Time.parse(time_b.strftime('%Y-%m-%d ') + BusinessTime::Config.beginning_of_workday) # Last day

  # All days in between
  duration_of_working_day = Time.parse(BusinessTime::Config.end_of_workday) - Time.parse(BusinessTime::Config.beginning_of_workday)
  result += (time_a.to_date.business_days_until(time_b.to_date) - 1) * duration_of_working_day

  # Make sure that sign is correct
  result *= direction
end