From 0df29bc7715b33c305d2b8098d1f75c67211ef1e Mon Sep 17 00:00:00 2001 From: Lars Kuhnt Date: Fri, 26 Apr 2024 11:44:45 +0200 Subject: [PATCH] review fixes and added comments --- lib/ice_cube/rules/weekly_rule.rb | 9 ++++++++- spec/examples/fixed_value_spec.rb | 2 +- spec/examples/schedule_spec.rb | 24 ++++++++++++++++-------- spec/examples/weekly_rule_spec.rb | 28 +++++++++++++++++++++++----- 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/lib/ice_cube/rules/weekly_rule.rb b/lib/ice_cube/rules/weekly_rule.rb index 038f983b..6c382d10 100644 --- a/lib/ice_cube/rules/weekly_rule.rb +++ b/lib/ice_cube/rules/weekly_rule.rb @@ -35,7 +35,14 @@ def realign(step_time, start_time) time = TimeUtil::TimeWrapper.new(start_time) offset = wday_offset(step_time, start_time) time.add(:day, offset) - super step_time, time.to_timezoneless_time + realigned_time = time.to_time + # when the realigned time is in a different hour, we need to adjust the + # time to the correct hour with a fixed timezone offset, otherwise + # the time will be off by an hour + # WARNING: if the next DST change is within the interval, the occurrences + # after the next DST change will be off by an hour because the timezone is fixed + realigned_time = time.to_timezoneless_time if realigned_time.hour != start_time.hour + super step_time, realigned_time end # Calculate how many days to the first wday validation in the correct diff --git a/spec/examples/fixed_value_spec.rb b/spec/examples/fixed_value_spec.rb index 93054416..ebee6153 100644 --- a/spec/examples/fixed_value_spec.rb +++ b/spec/examples/fixed_value_spec.rb @@ -14,4 +14,4 @@ expect(validation.validate(time_in_zone, start_time)).to eq 1 end end -end \ No newline at end of file +end diff --git a/spec/examples/schedule_spec.rb b/spec/examples/schedule_spec.rb index 52f4f149..ccc20d56 100644 --- a/spec/examples/schedule_spec.rb +++ b/spec/examples/schedule_spec.rb @@ -391,31 +391,39 @@ Time.utc(2014, 1, 2, 0o1, 34, 56)] end - context "Cairo timezone" do + context "Cairo timezone", system_time_zone: 'Africa/Cairo' do + require "active_support/time" + let(:schedule) do IceCube::Schedule.from_yaml("---\n:start_time:\n :time: 2022-05-05 22:20:00.000000000 Z\n :zone: Africa/Cairo\n:end_time:\n :time: 2022-05-06 21:40:00.000000000 Z\n :zone: Africa/Cairo\n:rrules:\n- :validations:\n :day:\n - 5\n :rule_type: IceCube::WeeklyRule\n :interval: 1\n :week_start: 1\n:rtimes: []\n:extimes: []\n") + # IceCube::Schedule.new(ActiveSupport::TimeZone['Africa/Cairo'].parse("2022-05-05 00:20:00")).tap do |schedule| + # schedule.add_recurrence_rule IceCube::Rule.weekly.day(:friday) + # end end it "has the correct start time" do expect(schedule.start_time.iso8601).to eq("2022-05-06T00:20:00+02:00") end - it "calculates the corret occurrences from 2024-04-24" do - ref_time = Time.utc(2024, 4, 24, 12, 0, 0) - occurrences = schedule.next_occurrences(3, ref_time) + it "has the correct start time timezone" do + expect(schedule.start_time.zone).to eq("EET") + end + + it "calculates the correct occurrences from 2024-04-24" do + occurrences = schedule.next_occurrences(3, Time.utc(2024, 4, 24, 12, 0, 0)) expect(occurrences.map(&:iso8601)).to eq([ "2024-04-26T00:20:00+03:00", "2024-05-03T00:20:00+03:00", - "2024-05-10T00:20:00+03:00" + "2024-05-10T00:20:00+03:00", ]) end - it "calculates the corret occurrences from 2024-04-21" do - occurrences = schedule.next_occurrences(3, Time.utc(2024, 4, 21, 12, 0, 0)) + it "calculates the correct occurrences from 2024-04-17" do + occurrences = schedule.next_occurrences(3, Time.utc(2024, 4, 17, 12, 0, 0)) expect(occurrences.map(&:iso8601)).to eq([ + "2024-04-19T00:20:00+02:00", "2024-04-26T01:20:00+03:00", "2024-05-03T00:20:00+03:00", - "2024-05-10T00:20:00+03:00" ]) end end diff --git a/spec/examples/weekly_rule_spec.rb b/spec/examples/weekly_rule_spec.rb index 362a4978..dc61bab3 100644 --- a/spec/examples/weekly_rule_spec.rb +++ b/spec/examples/weekly_rule_spec.rb @@ -411,19 +411,37 @@ module IceCube end describe :realign do - let(:cairo_tz) { ActiveSupport::TimeZone["Africa/Cairo"] } + require "active_support/time" + + let(:timezone_name) { "Africa/Cairo" } + let(:timezone) { ActiveSupport::TimeZone[timezone_name] } let(:utc_tz) { ActiveSupport::TimeZone["UTC"] } - let(:start_time) { cairo_tz.parse("2022-05-22 00:20:00") } + let(:start_time) { timezone.parse("2022-05-22 00:20:00") } let(:time) { utc_tz.parse("2024-04-24 12:00:00") } - let(:rule) { Rule.weekly(1, :monday).day(:friday) } + let(:recurrence_day) { :friday } + let(:rule) { Rule.weekly(1, :monday).day(recurrence_day) } subject { rule.realign(time, start_time) } - it { puts cairo_tz.parse("2024-04-26T00:20:00") } - it "realigns the start time to the correct time" do expect(subject.iso8601).to eq("2024-04-26T00:20:00+03:00") end + + context "Berlin timezone" do + let(:recurrence_day) { :sunday } + let(:timezone_name) { "Europe/Berlin" } + let(:start_time) { timezone.parse("2024-03-24 02:30:00") } + let(:time) { timezone.parse("2024-03-27 02:30:00") } + + # the next occurrence is on sunday within the DST shift + # where the clock is set forward from 02:00 to 03:00 + # so the next occurrence is on actually on 03:30 but this + # would result in faulty start times for the following + # occurrences (03:30 instead of 02:30) + it "realigns the start time to the correct time" do + expect(subject.iso8601).to eq("2024-03-31T02:30:00+02:00") + end + end end end end