diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 0e3e2e6b7..3b2ef0182 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -557,10 +557,6 @@ class Ticket < ApplicationModel end } - # get and set calendar settings - if sla_selected - TimeCalculation.config( sla_selected.data, sla_selected.timezone, time ) - end return sla_selected end @@ -609,13 +605,13 @@ class Ticket < ApplicationModel # first response if sla_selected.first_response_time - self.first_response_escal_date = TimeCalculation.dest_time( created_at, sla_selected.first_response_time ) + self.first_response_escal_date = TimeCalculation.dest_time( created_at, sla_selected.first_response_time, sla_selected.data, sla_selected.timezone ) # set ticket escalation self.escalation_time = self._escalation_calculation_higher_time( self.escalation_time, self.first_response_escal_date, self.first_response ) end if self.first_response# && !self.first_response_in_min - self.first_response_in_min = TimeCalculation.business_time_diff( self.created_at, self.first_response ) + self.first_response_in_min = TimeCalculation.business_time_diff( self.created_at, self.first_response, sla_selected.data, sla_selected.timezone ) end # set sla time if sla_selected.first_response_time && self.first_response_in_min @@ -629,13 +625,13 @@ class Ticket < ApplicationModel last_update = self.created_at end if sla_selected.update_time - self.update_time_escal_date = TimeCalculation.dest_time( last_update, sla_selected.update_time ) + self.update_time_escal_date = TimeCalculation.dest_time( last_update, sla_selected.update_time, sla_selected.data, sla_selected.timezone ) # set ticket escalation self.escalation_time = self._escalation_calculation_higher_time( self.escalation_time, self.update_time_escal_date, false ) end if self.last_contact_agent - self.update_time_in_min = TimeCalculation.business_time_diff( self.created_at, self.last_contact_agent ) + self.update_time_in_min = TimeCalculation.business_time_diff( self.created_at, self.last_contact_agent, sla_selected.data, sla_selected.timezone ) end # set sla time @@ -646,13 +642,13 @@ class Ticket < ApplicationModel # close time if sla_selected.close_time - self.close_time_escal_date = TimeCalculation.dest_time( self.created_at, sla_selected.close_time ) + self.close_time_escal_date = TimeCalculation.dest_time( self.created_at, sla_selected.close_time, sla_selected.data, sla_selected.timezone ) # set ticket escalation self.escalation_time = self._escalation_calculation_higher_time( self.escalation_time, self.close_time_escal_date, self.close_time ) end if self.close_time# && !self.close_time_in_min - self.close_time_in_min = TimeCalculation.business_time_diff( self.created_at, self.close_time ) + self.close_time_in_min = TimeCalculation.business_time_diff( self.created_at, self.close_time, sla_selected.data, sla_selected.timezone ) end # set sla time if sla_selected.close_time && self.close_time_in_min diff --git a/lib/business_time/business_minutes.rb b/lib/business_time/business_minutes.rb deleted file mode 100644 index b37527d3f..000000000 --- a/lib/business_time/business_minutes.rb +++ /dev/null @@ -1,99 +0,0 @@ -module BusinessTime - - class BusinessMinutes - def initialize(minutes) - @minutes = minutes - end - - def ago - Time.zone ? before(Time.zone.now) : before(Time.now) - end - - def from_now - Time.zone ? after(Time.zone.now) : after(Time.now) - end - - def after(time) - after_time = Time.roll_forward(time) - # Step through the minutes, skipping over non-business minutes - days = @minutes / 60 / 24 - hours = ( @minutes - ( days * 60 * 24 ) ) / 60 - minutes = @minutes - ( (days * 60 * 24 ) + (hours * 60) ) - if @minutes > 60 * 12 - - end - - local_sec = @minutes * 60 - loop = true - while (loop == true) do - a = after_time - if local_sec >= 60 * 60 - after_time = after_time + 1.hour - else - after_time = after_time + 1.minute - end - - # Ignore minutes before opening and after closing - if (after_time > Time.end_of_workday(after_time)) - after_time = after_time + off_minutes - if local_sec < 60 * 60 - after_time = after_time - 60 - else - after_time = after_time - 60 * 60 - end - next - end - - # Ignore weekends and holidays - while !Time.workday?(after_time) - after_time = Time.beginning_of_workday(after_time + 1.day) - a = after_time - end - diff = after_time - a - local_sec = local_sec - diff - - if local_sec <= 0 - loop = false - next - end - - end - after_time - end - alias_method :since, :after - - def before(time) - before_time = Time.roll_forward(time) - # Step through the hours, skipping over non-business hours - @minutes.times do - before_time = before_time - 1.minute - - # Ignore hours before opening and after closing - if (before_time < Time.beginning_of_workday(before_time)) - before_time = before_time - off_minutes - end - - # Ignore weekends and holidays - while !Time.workday?(before_time) - before_time = before_time - 1.day - end - end - before_time - end - - private - - def off_minutes - return @gap if @gap - if Time.zone - gap_end = Time.zone.parse(BusinessTime::Config.beginning_of_workday) - gap_begin = (Time.zone.parse(BusinessTime::Config.end_of_workday)-1.day) - else - gap_end = Time.parse(BusinessTime::Config.beginning_of_workday) - gap_begin = (Time.parse(BusinessTime::Config.end_of_workday) - 1.day) - end - @gap = gap_end - gap_begin - end - end - -end diff --git a/lib/business_time/core_ext/fixnum_minute.rb b/lib/business_time/core_ext/fixnum_minute.rb deleted file mode 100644 index af6a894de..000000000 --- a/lib/business_time/core_ext/fixnum_minute.rb +++ /dev/null @@ -1,11 +0,0 @@ -# hook into fixnum so we can say things like: -# 5.business_minutes.from_now -# 4.business_minutes.before(some_date_time) -class Fixnum - include BusinessTime - - def business_minutes - BusinessMinutes.new(self) - end - alias_method :business_minute, :business_minutes -end \ No newline at end of file diff --git a/lib/business_time/core_ext/time_fix.rb b/lib/business_time/core_ext/time_fix.rb deleted file mode 100644 index ce000b22b..000000000 --- a/lib/business_time/core_ext/time_fix.rb +++ /dev/null @@ -1,130 +0,0 @@ -# Add workday and weekday concepts to the Time class -class Time - class << self - - # 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. - 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 - - # 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. - 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 - - # 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. - def workday?(day) - Time.weekday?(day) && - !BusinessTime::Config.holidays.include?(day.to_date) - end - - # True if this time falls on a weekday. - def weekday?(day) - BusinessTime::Config.weekdays.include? day.wday - end - - def before_business_hours?(time) - time < beginning_of_workday(time) - end - - def after_business_hours?(time) - time > end_of_workday(time) - end - - # Rolls forward to the next beginning_of_workday - # when the time is outside of business hours - 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 + 1) - 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 - - end -end - -class Time - - 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 -#puts "--- #{time_a}-#{time_b} - #{direction}" - -# 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 - - result = 0 - - # All days in between - time_c = time_a - while time_c.to_i < time_b.to_i do - end_of_workday = Time.end_of_workday(time_c) - if !Time.workday?(time_c) - time_c = Time.beginning_of_workday(time_c) + 1.day -# puts 'VACATIONS! ' + time_c.to_s - end - if time_c.to_date == time_b.to_date - if end_of_workday < time_b - result += end_of_workday - time_c - break - else - result += time_b - time_c - break - end - else - result += end_of_workday - time_c - time_c = Time::roll_forward(end_of_workday) - end - result += 1 if end_of_workday.to_s =~ /23:59:59/ - end - - # Make sure that sign is correct - result *= direction - end - -end \ No newline at end of file diff --git a/lib/time_calculation.rb b/lib/time_calculation.rb index 04daa2060..f3e4608fc 100644 --- a/lib/time_calculation.rb +++ b/lib/time_calculation.rb @@ -1,10 +1,5 @@ -require 'business_time' -require 'business_time/business_minutes' -require 'business_time/core_ext/fixnum_minute' -require 'business_time/core_ext/time_fix' - module TimeCalculation - def self.config(config, timezone, start_time) + def self.working_hours(start_time, config, timezone) time_diff = 0 if timezone begin @@ -15,50 +10,286 @@ module TimeCalculation puts e.backtrace end end - beginning_of_workday = Time.parse("1977-10-27 #{config['beginning_of_workday']}") + time_diff - if beginning_of_workday - config['beginning_of_workday'] = "#{beginning_of_workday.hour}:#{beginning_of_workday.min}" - end - end_of_workday = Time.parse("1977-10-27 #{config['end_of_workday']}") + time_diff - if end_of_workday - config['end_of_workday'] = "#{end_of_workday.hour}:#{end_of_workday.min}" - end - BusinessTime::Config.beginning_of_workday = config['beginning_of_workday'] - BusinessTime::Config.end_of_workday = config['end_of_workday'] - days = [] - ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'].each {|day| - if config[day] - days.push day.downcase.to_sym + beginning_of_workday = Time.parse("1977-10-27 #{config['beginning_of_workday']}") + end_of_workday = Time.parse("1977-10-27 #{config['end_of_workday']}") - 3600 + config_ok = false + working_hours = {} + [:Mon, :Tue, :Wed, :Thu, :Fri, :Sat, :Sun].each {|day| + working_hours[day] = [] + if config[day.to_s] == true || config[day.to_s] == day.to_s + config_ok = true + (0..23).each {|hour| + time = Time.parse("1977-10-27 #{hour}:00:00") + if time >= beginning_of_workday && time <= end_of_workday + working_hours[day].push true + else + working_hours[day].push nil + end + } end } - BusinessTime::Config.work_week = days - holidays = [] - if config['holidays'] - config['holidays'].each {|holiday| - date = Date.parse( holiday ) - holidays.push date.to_date + + if !config_ok + raise "sla config is invalid! " + config.inspect + end + + # shift working hours / if needed + if time_diff && time_diff != 0 + + hours_to_shift = (time_diff / 3600 ).round + move_items = { + :Mon => [], + :Tue => [], + :Wed => [], + :Thu => [], + :Fri => [], + :Sat => [], + :Sun => [], + } + (1..hours_to_shift).each {|count| + working_hours.each {|day, value| + if working_hours[day] + to_move = working_hours[day].shift + if day == :Mon + move_items[:Tue].push to_move + elsif day == :Tue + move_items[:Wed].push to_move + elsif day == :Wed + move_items[:Thu].push to_move + elsif day == :Thu + move_items[:Fri].push to_move + elsif day == :Fri + move_items[:Sat].push to_move + elsif day == :Sat + move_items[:Sun].push to_move + elsif day == :Sun + move_items[:Mon].push to_move + end + end + } + } + move_items.each {|day, value| + value.each {|item| + working_hours[day].push item + } } end - BusinessTime::Config.holidays = holidays + return working_hours end - def self.business_time_diff(start_time, end_time) + def self.business_time_diff(start_time, end_time, config, timezone = '') if start_time.class == String start_time = Time.parse( start_time.to_s + 'UTC' ) end if end_time.class == String end_time = Time.parse( end_time.to_s + 'UTC' ) end - diff = start_time.business_time_until( end_time ) / 60 + + working_hours = self.working_hours(start_time, config, timezone) + + week_day_map = { + 1 => :Mon, + 2 => :Tue, + 3 => :Wed, + 4 => :Thu, + 5 => :Fri, + 6 => :Sat, + 0 => :Sun, + } + + count = 0 + calculation = true + first_loop = true + while calculation do + week_day = start_time.wday + day = start_time.day + month = start_time.month + year = start_time.year + hour = start_time.hour + + + # check if it's vacation day + if config + if config['holidays'] + if config['holidays'].include?("#{year}-#{month}-#{day}") + + # jump to next day + start_time = start_time.beginning_of_day + 86400 + next + end + end + end + + # check if it's countable day + if working_hours[ week_day_map[week_day] ].empty? + + # jump to next day + start_time = start_time.beginning_of_day + 86400 + next + end + + # fillup to first full hour + if first_loop + diff = end_time - start_time + + if diff > 59 * 60 + diff = start_time - start_time.beginning_of_hour + end + start_time += diff + + # check if it's countable hour + if working_hours[ week_day_map[week_day] ][ hour ] + count += diff + end + end + first_loop = false + + # loop to next hour + (hour..23).each { |next_hour| + + # check if end time is lower + if start_time >= end_time + calculation = false + break + end + + # check if end_time is within this hour + diff = end_time - start_time + if diff > 59 * 60 + diff = 3600 + end + + # keep it in current day + if next_hour == 23 + start_time += diff-1 + else + start_time += diff + end + + # check if it's business hour and count + if working_hours[ week_day_map[week_day] ][ next_hour ] + count += diff + end + } + + # loop to next day + start_time = start_time.beginning_of_day + 86400 + end + + diff = count / 60 diff.round end - def self.dest_time(start_time, diff_in_min) + def self.dest_time(start_time, diff_in_min, config, timezone = '') if start_time.class == String start_time = Time.parse( start_time.to_s + ' UTC' ) end - dest_time = diff_in_min.round.business_minute.after( start_time ) - return dest_time + + # loop + working_hours = self.working_hours(start_time, config, timezone) + + week_day_map = { + 1 => :Mon, + 2 => :Tue, + 3 => :Wed, + 4 => :Thu, + 5 => :Fri, + 6 => :Sat, + 0 => :Sun, + } + + count = diff_in_min * 60 + calculation = true + first_loop = true + while calculation do + week_day = start_time.wday + day = start_time.day + month = start_time.month + year = start_time.year + hour = start_time.hour +#puts "start outer loop #{start_time}-#{week_day}-#{year}-#{month}-#{day}-#{hour}|c#{count}" + + # check if it's vacation day + if config + if config['holidays'] + if config['holidays'].include?("#{year}-#{month}-#{day}") + + # jump to next day + start_time = start_time.beginning_of_day + 86400 + next + end + end + end + + # check if it's countable day + if working_hours[ week_day_map[week_day] ].empty? + + # jump to next day + start_time = start_time.beginning_of_day + 86400 + next + end + + # fillup to first full hour + if first_loop + + # get rest of this hour + diff = 3600 - (start_time - start_time.beginning_of_hour) + start_time += diff + + # check if it's countable hour + if working_hours[ week_day_map[week_day] ][ hour ] + count -= diff + end + + # start on next hour of we moved to next + if diff != 0 + hour += 1 + end + end + + first_loop = false + + # loop to next hour + (hour..23).each { |next_hour| + + diff = 3600 + + # check if count positiv + if count <= 0 + calculation = false + break + end + + # check if it's business hour and count + if working_hours[ week_day_map[week_day] ][ next_hour ] + # check if count is within this hour + if count > 59 * 60 + diff = 3600 + else + diff = count + end + count -= diff + end + + # keep it in current day + if next_hour == 23 + start_time += diff-1 + else + start_time += diff + end + } + + # check if count positiv + if count <= 0 + calculation = false + break + end + + # loop to next day + start_time = start_time.beginning_of_day + 86400 + end + + return start_time end end diff --git a/test/unit/ticket_test.rb b/test/unit/ticket_test.rb index 96672efb8..6f00d1d2f 100644 --- a/test/unit/ticket_test.rb +++ b/test/unit/ticket_test.rb @@ -455,7 +455,7 @@ class TicketTest < ActiveSupport::TestCase assert( ticket, "ticket created" ) assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify' ) - # set sla's for timezone "Europe/Berlin" (+1), so UTC times are 8:00-17:00 + # set sla's for timezone "Europe/Berlin" wintertime (+1), so UTC times are 8:00-17:00 sla = Sla.create( :name => 'test sla 1', :condition => {}, @@ -473,17 +473,16 @@ class TicketTest < ActiveSupport::TestCase :created_by_id => 1, ) ticket = Ticket.find(ticket.id) - assert_equal( ticket.escalation_time.gmtime.to_s, '2013-03-21 12:00:00 UTC', 'ticket.escalation_time verify 1' ) - assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-03-21 12:00:00 UTC', 'ticket.first_response_escal_date verify 1' ) - assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-03-21 13:00:00 UTC', 'ticket.update_time_escal_date verify 1' ) - assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-03-21 14:00:00 UTC', 'ticket.close_time_escal_date verify 1' ) + assert_equal( ticket.escalation_time.gmtime.to_s, '2013-03-21 11:30:00 UTC', 'ticket.escalation_time verify 1' ) + assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-03-21 11:30:00 UTC', 'ticket.first_response_escal_date verify 1' ) + assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-03-21 12:30:00 UTC', 'ticket.update_time_escal_date verify 1' ) + assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-03-21 13:30:00 UTC', 'ticket.close_time_escal_date verify 1' ) delete = sla.destroy assert( delete, "sla destroy" ) delete = ticket.destroy assert( delete, "ticket destroy" ) - ticket = Ticket.create( :title => 'some title äöüß', :group => Group.lookup( :name => 'Users'), @@ -498,7 +497,7 @@ class TicketTest < ActiveSupport::TestCase assert( ticket, "ticket created" ) assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify' ) - # set sla's for timezone "Europe/Berlin" (+1), so UTC times are 8:00-17:00 + # set sla's for timezone "Europe/Berlin" summertime (+2), so UTC times are 7:00-16:00 sla = Sla.create( :name => 'test sla 1', :condition => {}, @@ -516,16 +515,60 @@ class TicketTest < ActiveSupport::TestCase :created_by_id => 1, ) ticket = Ticket.find(ticket.id) - assert_equal( ticket.escalation_time.gmtime.to_s, '2013-10-21 13:00:00 UTC', 'ticket.escalation_time verify 1' ) - assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-10-21 13:00:00 UTC', 'ticket.first_response_escal_date verify 1' ) - assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-10-21 14:00:00 UTC', 'ticket.update_time_escal_date verify 1' ) - assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-10-21 15:00:00 UTC', 'ticket.close_time_escal_date verify 1' ) + assert_equal( ticket.escalation_time.gmtime.to_s, '2013-10-21 11:30:00 UTC', 'ticket.escalation_time verify 1' ) + assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-10-21 11:30:00 UTC', 'ticket.first_response_escal_date verify 1' ) + assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-10-21 12:30:00 UTC', 'ticket.update_time_escal_date verify 1' ) + assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-10-21 13:30:00 UTC', 'ticket.close_time_escal_date verify 1' ) delete = ticket.destroy assert( delete, "ticket destroy" ) delete = sla.destroy assert( delete, "sla destroy" ) + + ticket = Ticket.create( + :title => 'some title äöüß', + :group => Group.lookup( :name => 'Users'), + :customer_id => 2, + :ticket_state => Ticket::State.lookup( :name => 'new' ), + :ticket_priority => Ticket::Priority.lookup( :name => '2 normal' ), + :created_at => '2013-10-21 06:30:00 UTC', + :updated_at => '2013-10-21 06:30:00 UTC', + :updated_by_id => 1, + :created_by_id => 1, + ) + assert( ticket, "ticket created" ) + assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify' ) + + # set sla's for timezone "Europe/Berlin" summertime (+2), so UTC times are 7:00-16:00 + sla = Sla.create( + :name => 'test sla 1', + :condition => {}, + :data => { + "Mon"=>"Mon", "Tue"=>"Tue", "Wed"=>"Wed", "Thu"=>"Thu", "Fri"=>"Fri", "Sat"=>"Sat", "Sun"=>"Sun", + "beginning_of_workday" => "9:00", + "end_of_workday" => "18:00", + }, + :timezone => 'Europe/Berlin', + :first_response_time => 120, + :update_time => 180, + :close_time => 240, + :active => true, + :updated_by_id => 1, + :created_by_id => 1, + ) + ticket = Ticket.find(ticket.id) + assert_equal( ticket.escalation_time.gmtime.to_s, '2013-10-21 09:00:00 UTC', 'ticket.escalation_time verify 1' ) + assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-10-21 09:00:00 UTC', 'ticket.first_response_escal_date verify 1' ) + assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-10-21 10:00:00 UTC', 'ticket.update_time_escal_date verify 1' ) + assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-10-21 11:00:00 UTC', 'ticket.close_time_escal_date verify 1' ) + + delete = sla.destroy + assert( delete, "sla destroy" ) + + delete = ticket.destroy + assert( delete, "ticket destroy" ) + end end diff --git a/test/unit/working_time_test.rb b/test/unit/working_time_test.rb index c03abc95e..4ea11697d 100644 --- a/test/unit/working_time_test.rb +++ b/test/unit/working_time_test.rb @@ -73,6 +73,8 @@ class WorkingTimeTest < ActiveSupport::TestCase ], }, }, + + # test 5 { :start => '2013-02-28 17:00:00', :end => '2013-02-28 23:59:59', @@ -87,10 +89,158 @@ class WorkingTimeTest < ActiveSupport::TestCase 'end_of_workday' => '6:00 pm', }, }, + + # test 6 + { + :start => '2013-02-28 17:00:00', + :end => '2013-03-08 23:59:59', + :diff => 3660, + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 7 + { + :start => '2012-02-28 17:00:00', + :end => '2013-03-08 23:59:59', + :diff => 160860, + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 8 + { + :start => '2013-02-28 17:01:00', + :end => '2013-02-28 18:10:59', + :diff => 61, + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 9 + { + :start => '2013-02-28 18:01:00', + :end => '2013-02-28 18:10:59', + :diff => 0, + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 10 / summertime + { + :start => '2013-02-28 18:01:00', + :end => '2013-02-28 18:10:59', + :diff => 0, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 11 / summertime + { + :start => '2013-02-28 17:01:00', + :end => '2013-02-28 17:10:59', + :diff => 0, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 12 / wintertime + { + :start => '2013-08-29 17:01:00', + :end => '2013-08-29 17:10:59', + :diff => 0, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 13 / summertime + { + :start => '2013-02-28 16:01:00', + :end => '2013-02-28 16:10:59', + :diff => 10, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 14 / wintertime + { + :start => '2013-08-29 16:01:00', + :end => '2013-08-29 16:10:59', + :diff => 0, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, ] tests.each { |test| - TimeCalculation.config( test[:config], nil, test[:start] ) - diff = TimeCalculation.business_time_diff( test[:start], test[:end] ) + diff = TimeCalculation.business_time_diff( test[:start], test[:end], test[:config], test[:timezone] ) assert_equal( diff, test[:diff], 'diff' ) } end @@ -178,6 +328,7 @@ class WorkingTimeTest < ActiveSupport::TestCase }, }, + # test 6 { :start => '2012-12-17 08:00:00', @@ -241,10 +392,112 @@ class WorkingTimeTest < ActiveSupport::TestCase 'end_of_workday' => '6:00 pm', }, }, + + # test 11 / summertime + { + :start => '2013-03-08 21:20:15', + :dest_time => '2013-03-11 09:00:00', + :diff => 120, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 12 / wintertime + { + :start => '2013-09-06 21:20:15', + :dest_time => '2013-09-09 08:00:00', + :diff => 120, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 13 / wintertime + { + :start => '2013-10-21 06:30:00', + :dest_time => '2013-10-21 09:00:00', + :diff => 120, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '9:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 14 / wintertime + { + :start => '2013-10-21 04:34:15', + :dest_time => '2013-10-21 09:00:00', + :diff => 120, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '9:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 15 / wintertime + { + :start => '2013-10-20 22:34:15', + :dest_time => '2013-10-21 09:00:00', + :diff => 120, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '9:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 16 / wintertime + { + :start => '2013-10-21 07:00:15', + :dest_time => '2013-10-21 09:00:00', + :diff => 120, + :timezone => 'Europe/Berlin', + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '9:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + ] tests.each { |test| - TimeCalculation.config( test[:config], nil, test[:start] ) - dest_time = TimeCalculation.dest_time( test[:start] + ' UTC', test[:diff] ) + dest_time = TimeCalculation.dest_time( test[:start] + ' UTC', test[:diff], test[:config], test[:timezone] ) assert_equal( dest_time.gmtime, Time.parse( test[:dest_time] + ' UTC' ), "dest time - #{test[:dest_time].to_s}" ) } end