diff --git a/spec/entity_spec.cr b/spec/entity_spec.cr index 5b0683e..d693f21 100644 --- a/spec/entity_spec.cr +++ b/spec/entity_spec.cr @@ -3,10 +3,43 @@ require "./spec_helper" module Dayoff::Test extend self - describe "can check same date" do + it "planned can calc in range" do planned_date = PlannedDate.new(t(1, 12), 8) - date = t(1, 20) - res = planned_date.same_date? date - res.should be_true + t1 = t(1, 0) + t2 = t(2, 0) + res = planned_date.in_range t1, t2 + res.total_hours.should eq 8 + end + + it "planned can calc in range 2" do + planned_date = PlannedDate.new(t(3, 0), 8) + t1 = t(1, 0) + t2 = t(2, 0) + res = planned_date.in_range t1, t2 + res.total_hours.should eq 0 + end + + it "planned can calc in range 2" do + planned_date = PlannedDate.new(d(1), 8) + t1 = t(1, 0).at_beginning_of_day + t2 = t(1, 0).at_end_of_day + res = planned_date.in_range t1, t2 + res.total_hours.should eq 8 + end + + it "worked can calc in range" do + work_record = WorkRecord.new(t(1, 10), t(1, 20)) + t1 = t(1, 15).at_beginning_of_day + t2 = t(1, 15) + res = work_record.in_range t1, t2 + res.total_hours.should eq 5 + end + + it "worked can calc in range 2" do + work_record = WorkRecord.new(t(1, 10), t(1, 20)) + t1 = t(2, 15).at_beginning_of_day + t2 = t(2, 15) + res = work_record.in_range t1, t2 + res.total_hours.should eq 0 end end diff --git a/spec/profile_spec.cr b/spec/profile_spec.cr index e4fb326..017f8ea 100644 --- a/spec/profile_spec.cr +++ b/spec/profile_spec.cr @@ -18,15 +18,6 @@ module Dayoff::Test end describe Profile do - it "can calc work hours" do - storage = MemoryStorage.new - storage.set_work_records [ - WorkRecord.new(t(1, 10), t(1, 20)), - ] - prof = Profile.new(storage) - prof.get_work_hours(t(2, 0)).total_hours.should eq 10 - end - it "can write new record" do storage = MemoryStorage.new storage.set_work_records [ @@ -54,27 +45,6 @@ module Dayoff::Test records.last.finish.should eq finish_time end - it "can calc planned hours" do - prof = create_profile - span = prof.get_planned_hours t(3, 12) - expected = 8 * 3 - expected.should eq span.total_hours - end - - it "can calc work hours" do - prof = create_profile - span = prof.get_work_hours t(3, 12) - expected = 10 * 2 - expected.should eq span.total_hours - end - - it "can calc remaining time" do - prof = create_profile - span = prof.remaining_time t(3, 12) - expected = 8 * 3 - 10 * 2 - expected.should eq span.total_hours - end - it "not start twice" do prof = create_profile start_time = t(3, 10, 0) @@ -95,10 +65,17 @@ module Dayoff::Test end end + it "can calc remaining time" do + prof = create_profile + span = prof.remaining_time t(3, 12) + expected = 8 * 3 - 10 * 2 + expected.should eq span.total_hours + end + it "can calc diff on concrete date" do prof = create_profile - span = prof.date_status d(1) - span.total_hours.should eq -2 + span = prof.date_status t(1, 15) + span.total_hours.should eq 3 end end end diff --git a/src/dayoff/entities.cr b/src/dayoff/entities.cr index 441eb0f..421daa0 100644 --- a/src/dayoff/entities.cr +++ b/src/dayoff/entities.cr @@ -23,12 +23,12 @@ module Dayoff def initialize(@date : Time, @hours : Int32) end - def time_span : Time::Span - Time::Span.new(hours: hours, minutes: 0, seconds: 0) - end - - def same_date?(d : Time) : Bool - @date.date == d.date + def in_range(from_time : Time, to_time : Time) : Time::Span + if @date >= from_time && @date < to_time + Time::Span.new(hours: @hours, minutes: 0, seconds: 0) + else + Time::Span.zero + end end end @@ -61,32 +61,28 @@ module Dayoff !@finish.nil? end - def finished_to_time?(time : Time) : Bool - @finish && @finish <= time - end - - def calc_span(time : Time) : Time::Span - if @finish.nil? - if @start <= time - time - @start - else - Time::Span.zero - end + def in_range(from_time : Time, to_time : Time) : Time::Span + if finished? + in_range_finished from_time, to_time else - if time > finish! - finish! - @start - elsif time > @start - time - @start - else - Time::Span.zero - end + in_range_not_finished from_time, to_time end end - def on_date(d : Time) : Time::Span - if @start.date == d.date - fin = @finish || d - fin - start + private def in_range_finished(from_time : Time, to_time : Time) : Time::Span + if @start <= to_time && finish! >= from_time + normalized_start = Math.max(@start, from_time) + normalized_finish = Math.min(finish!, to_time) + normalized_finish - normalized_start + else + Time::Span.zero + end + end + + private def in_range_not_finished(from_time : Time, to_time : Time) : Time::Span + if @start <= to_time + normalized_start = Math.max(@start, from_time) + to_time - normalized_start else Time::Span.zero end diff --git a/src/dayoff/profile.cr b/src/dayoff/profile.cr index 4e8759b..757fe17 100644 --- a/src/dayoff/profile.cr +++ b/src/dayoff/profile.cr @@ -21,21 +21,8 @@ module Dayoff @wrecords = @storage.get_work_records end - def get_planned_hours(on_time : Time) : Time::Span - check_date = on_time.at_beginning_of_day - @pdates.reduce(Time::Span.zero) do |acc, wd| - if wd.date <= check_date - acc + wd.time_span - else - acc - end - end - end - - def get_work_hours(on_time : Time) : Time::Span - @wrecords.reduce(Time::Span.zero) do |acc, wr| - acc + wr.calc_span on_time - end + private def started_point + @wrecords.find { |x| x.started? } end def started? : Bool @@ -65,36 +52,33 @@ module Dayoff @storage.set_work_records @wrecords end - def remaining_time(on_time : Time) : Time::Span - planned = get_planned_hours on_time - worked = get_work_hours on_time - planned - worked - end - - def date_status(d : Time) : Time::Span - planned = get_planned_hours_on_date d - worked = get_work_hours_on_date d - planned - worked - end - - private def get_planned_hours_on_date(d : Time) : Time::Span - @pdates.reduce(Time::Span.zero) do |acc, wd| - if wd.same_date? d - acc + wd.time_span - else - acc - end + def get_planned(from_time : Time, to_time : Time) : Time::Span + @pdates.reduce(Time::Span.zero) do |acc, pd| + acc + pd.in_range(from_time, to_time) end end - private def get_work_hours_on_date(d : Time) : Time::Span + def get_worked(from_time : Time, to_time : Time) : Time::Span @wrecords.reduce(Time::Span.zero) do |acc, wr| - acc + wr.on_date d + acc + wr.in_range(from_time, to_time) end end - private def started_point - @wrecords.find { |x| x.started? } + private def zero_time : Time + location = Time::Location.load("Europe/Moscow") + Time.local(1, 1, 1, 0, 0, location: location) + end + + def remaining_time(on_time : Time) : Time::Span + planned = get_planned zero_time, on_time + worked = get_worked zero_time, on_time + planned - worked + end + + def date_status(date : Time) : Time::Span + planned = get_planned date.at_beginning_of_day, date.at_end_of_day + worked = get_worked date.at_beginning_of_day, date + planned - worked end end end