我想在Ruby中计算两个日期之间的“早晨”和“晚上”工作时间。
“早上”工作时间从06:00:00开始,到21:59:59结束
“晚上”工作时间从22:00:00开始,到05:59:59结束
例如,员工在2014-06-04 21:45开始工作,并在2014-06-05 05:45完成,这意味着,总结应该是:
答案 0 :(得分:1)
这可以使用biz
gem:
morning_schedule = Biz::Schedule.new do |config|
config.hours = {
mon: {'06:00' => '22:00'},
tue: {'06:00' => '22:00'},
wed: {'06:00' => '22:00'},
thu: {'06:00' => '22:00'},
fri: {'06:00' => '22:00'}
}
end
evening_schedule = Biz::Schedule.new do |config|
config.hours = {
mon: {'00:00' => '06:00', '22:00' => '24:00'},
tue: {'00:00' => '06:00', '22:00' => '24:00'},
wed: {'00:00' => '06:00', '22:00' => '24:00'},
thu: {'00:00' => '06:00', '22:00' => '24:00'},
fri: {'00:00' => '06:00', '22:00' => '24:00'}
}
end
# morning hours worked
morning_schedule.within(
Time.new(2014, 6, 4, 21, 45),
Time.new(2014, 6, 5, 5, 45)
)
# evening hours worked
evening_schedule.within(
Time.new(2014, 6, 4, 21, 45),
Time.new(2014, 6, 5, 5, 45)
)
确定每个工作时间类型的持续时间后,可以执行后续计算,例如工资系数。
答案 1 :(得分:0)
您可以使用执行此类计算的working_hours gem:https://github.com/intrepidd/working_hours
答案 2 :(得分:-2)
这是一个丑陋的实现(应该适用于任何时间范围):
def time_test(tstr1, tstr2)
t1 = Time.parse(tstr1)
t2 = Time.parse(tstr2)
morning_seconds = 0
evening_seconds = 0
while t1 < t2 do
# if we are starting during morning hours...
if t1.hour >= 6 && t1.hour < 22
# this sets the end of morning hours for the current day...
tend = t1.change(hour: 22)
# but our actual morning_end should be the lesser of the range end time
# and the end of current days' working hours
morning_end = tend < t2 ? tend : t2
# increment our seconds with the difference between start time and morning end
morning_seconds += morning_end - t1
# set our start time to morning_end. if morning_end == t2, then we'll exit
# the while loop, else we'll process some evening hours
t1 = morning_end
# if we are starting during evening hours (at end of day)
elsif t1.hour >= 22
# same as above, except that the potential end time needs to increment the day
# as well as the hour
tend = t1.tomorrow.change(hour: 6)
evening_end = tend < t2 ? tend : t2
evening_seconds += evening_end - t1
t1 = evening_end
# if we are starting during evening hours (at beginning of day)
elsif t1.hour < 6
tend = t1.change(hour: 6)
evening_end = tend < t2 ? tend : t2
evening_seconds += evening_end - t1
t1 = evening_end
end
end
{
morning: morning_seconds / 3600,
evening: evening_seconds / 3600,
total: (morning_seconds + evening_seconds) / 3600
}
end
time_test('2014-06-04 21:45', '2014-06-05 05:45')
# => {:morning=>0.25, :evening=>7.75, :total=>8.0}
这是一种稍微漂亮的递归方式:
def time_test(tstr1, tstr2)
_t1 = Time.parse(tstr1)
t2 = Time.parse(tstr2)
runner = lambda do |t1, ms, es|
return {
morning: ms / 3600, evening: es / 3600, total: (ms + es) / 3600
} if t1 >= t2
if t1.hour >= 6 && t1.hour < 22
tend = t1.change(hour: 22)
morning_end = tend < t2 ? tend : t2
runner.call(morning_end, ms + (morning_end - t1), es)
elsif t1.hour >= 22
tend = t1.tomorrow.change(hour: 6)
evening_end = tend < t2 ? tend : t2
runner.call(evening_end, ms, es + (evening_end - t1))
elsif t1.hour < 6
tend = t1.change(hour: 6)
evening_end = tend < t2 ? tend : t2
runner.call(evening_end, ms, es + (evening_end - t1))
end
end
runner.call(_t1, 0, 0)
end