Делу - время, потехе - час
09.10.2013 в 18:00 ruby gem developВремя самое ценное, что у нас есть и его учет - это очень важно! Немного пафосно, но от реальности не убежишь. :) Так вот... В одном из проектов мне понадобился учет рабочего времени. Т.е. не просто "пришел-ушел-прогулял", а в плане планирования рабочего времени на выполнение той или иной задачи. Например: на выполнение очень важной задачи нам отвели 10 часов, а рабочий день у многих из нас, скажем, 8 часов и еще бывают выходные (что это?!). Хотя многие "руководители" и "очень важные начальники" считают, что 24 часа, а то и 36! И никаких выходных! :) Как нам выставить конечный срок выполнения задачи, если она поступила к нам, скажем, в пятницу (ура!) в 16:45 (троекратное ура!)? Можно, конечно, изобрести велосипед и написать функцию с кучей условий (обед? вечер? ночь? выходные?), которая будет высчитывать конечный срок исполнения из полученных начала выполнения и времени на выполнение (в часах или минутах). Я, признаться, собирался именно так и поступить. И тут, совершенно случайно, в ленте твиттера проскочил пост от @rubygems о том, что он рад мне помочь в этом - есть (оказывается) такой gem workpattern. Он умеет все это делать в лучшем виде!
Все объясняет простой пример кода:
1 # пишем инициалайзер (например config/initializers/workpattern.rb), ибо паттерны именованые и создаются единожды при старте приложения
2 # разумеентся их можно создавать в runtime, но не забывайте их удалять, иначе получите exception при повторном создании
3
4 # создаем новый паттерн
5 MyCoolApp::Application.config.workpattern = Workpattern.new('8х5 Workpattern', 2013, 01)
6 # выходные у нас есть, что бы кто не говорил!
7 MyCoolApp::Application.config.workpattern.resting(days: :weekend)
8 # ночью (с 00:00 до 08:59) мы спим (ага!)
9 MyCoolApp::Application.config.workpattern.resting(days: :weekday, from_time: Workpattern.clock(0, 0), to_time: Workpattern.clock(8, 59))
10 # в обед (с 13:00 до 13:59) мы обедаем (ваш КО)
11 MyCoolApp::Application.config.workpattern.resting(days: :weekday, from_time: Workpattern.clock(13, 0), to_time: Workpattern.clock(13, 59))
12 # вечером (с 18:00 до 23:59) решаем личные проблемы
13 MyCoolApp::Application.config.workpattern.resting(days: :weekday, from_time: Workpattern.clock(18, 0), to_time: Workpattern.clock(23, 59))
14
15 # бла-бла-бла...
16
17 # простой хелпер для высчитывания конечного срока
18 def get_datetime start_datetime, duration, all_arround_day = false
19 unless all_arround_day # класс обслуживания НЕ круглосуточный (8х5)
20 return MyCoolApp::Application.config.workpattern.calc(start_datetime, duration.minutes)
21 else # класс обслуживания круглосуточный (24х7)
22 return (start_datetime + duration.hours)
23 end
24 end
25
26 # бла-бла-бла...
27
28 # GET /incedents/new
29 def new
30 @incedent = Incedent.new
31
32 # бла-бла-бла...
33
34 if params[:service_class_id]
35 # у нас присутствует класс обслуживания с указанными заранее параметрами срока исполнения и т.п.
36 @incedent.service_class = ServiceClass.find(params[:service_class_id])
37
38 # бла-бла-бла...
39
40 # performance_hours - количество часов на выполнение в данном классе обслуживания
41 # all_around_day = true - круглосуточно
42 @incedent.finish_at = get_datetime(DateTime.now, @incedent.service_class.performance_hours, @incedent.service_class.all_around_day)
43 else
44 @incedent.finish_at = get_datetime(DateTime.now, 8) # по умолчанию на выполнение 8 рабочих часов
45 end
46
47 respond_to do |format|
48 format.html # new.html.erb
49 end
50 end
Я полагаю дальнейшие объяснения излишни, все и так ясно из примера кода. Повторюсь, что создавать статичные паттерны лучше в инициалайзере, но если есть необходимость можно клепать их прямо в runtime.
Удачного программирования!