Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed use of `delegate` method added in [66f1d797](https://github.com/ice-cube-ruby/ice_cube/commit/66f1d797092734563bfabd2132c024c7d087f683) , reverting to previous implementation. ([#522](https://github.com/ice-cube-ruby/ice_cube/pull/522)) by [@pacso](https://github.com/pacso)

### Fixed
- Fix for weekly occurrences when the next occurrence happens within a DST switch timespan ([#551](https://github.com/ice-cube-ruby/ice_cube/pull/551)) by [@larskuhnt](https://github.com/larskuhnt)
- Fix for weekly interval results when requesting `occurrences_between` on a narrow range ([#487](https://github.com/seejohnrun/ice_cube/pull/487)) by [@jakebrady5](https://github.com/jakebrady5)
- When using a rule with hour_of_day validations, and asking for occurrences on the day that DST skips forward, valid occurrences would be missed. ([#464](https://github.com/seejohnrun/ice_cube/pull/464)) by [@jakebrady5](https://github.com/jakebrady5)
- Include `exrules` when exporting a schedule to YAML, JSON or a Hash. ([#519](https://github.com/ice-cube-ruby/ice_cube/pull/519)) by [@pacso](https://github.com/pacso)
Expand Down
2 changes: 1 addition & 1 deletion lib/ice_cube/rules/weekly_rule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ 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_time
super step_time, time.to_timezoneless_time
end

# Calculate how many days to the first wday validation in the correct
Expand Down
16 changes: 16 additions & 0 deletions lib/ice_cube/time_util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,22 @@ def to_time
TimeUtil.build_in_zone(parts, @base)
end

# This is used keep the correct hour within the interval during DST
# changes. It will use the time from the schedule start time to lock the
# hour.
def to_timezoneless_time
unwrapped_time = to_time
Time.new(
unwrapped_time.year,
unwrapped_time.month,
unwrapped_time.day,
@time.hour,
@time.min,
@time.sec,
unwrapped_time.utc_offset
)
end

# DST-safely add an interval of time to the wrapped time
def add(type, val)
type = :day if type == :wday
Expand Down
17 changes: 17 additions & 0 deletions spec/examples/fixed_value_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require "spec_helper"

RSpec.describe IceCube::Validations::HourOfDay::Validation do

describe :validate do
let(:timezone) { "Africa/Cairo" }
let(:time) { "2024-05-03 00:20:00" }
let(:time_in_zone) { ActiveSupport::TimeZone[timezone].parse(time) }
let(:start_time) { ActiveSupport::TimeZone[timezone].parse("2024-04-26 01:20:00") }

let(:validation) { IceCube::Validations::HourOfDay::Validation.new(nil) }

it "returns the correct offset for the same hour" do
expect(validation.validate(time_in_zone, start_time)).to eq 1
end
end
end
29 changes: 29 additions & 0 deletions spec/examples/schedule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,35 @@
expect(next_hours).to eq [Time.utc(2014, 1, 2, 0o0, 34, 56),
Time.utc(2014, 1, 2, 0o1, 34, 56)]
end

context "Cairo timezone" do
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")
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)
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"
])
end

it "calculates the corret occurrences from 2024-04-21" do
occurrences = schedule.next_occurrences(3, Time.utc(2024, 4, 21, 12, 0, 0))
expect(occurrences.map(&:iso8601)).to eq([
"2024-04-26T01:20:00+03:00",
"2024-05-03T00:20:00+03:00",
"2024-05-10T00:20:00+03:00"
])
end
end
end

describe :next_occurrence do
Expand Down
16 changes: 16 additions & 0 deletions spec/examples/time_util_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,21 @@ module IceCube
end
end
end

describe :dst_change do
let(:timezone) { "Africa/Cairo" }
let(:time) { "2024-04-26 00:20:00" }
let(:time_in_zone) { ActiveSupport::TimeZone[timezone].parse(time) }

subject { TimeUtil.dst_change(time_in_zone) }

it { is_expected.to eql(1) }

context "when time is not on a DST change" do
let(:time) { "2024-04-25 00:20:00" }

it { is_expected.to be_nil }
end
end
end
end
35 changes: 35 additions & 0 deletions spec/examples/weekly_rule_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -390,5 +390,40 @@ module IceCube
end
end
end

context "when start time is within a timezone shift in Africa/Cairo timezone", system_time_zone: "UTC" do
let(:cairo_tz) { ActiveSupport::TimeZone["Africa/Cairo"] }
let(:utc_tz) { ActiveSupport::TimeZone["UTC"] }
let(:start_time) { cairo_tz.parse("2022-05-22 00:20:00") }
let(:rule) { Rule.weekly(1, :monday).day(:friday) }

it "parses the start time correctly" do
expect(start_time.iso8601).to eq("2022-05-22T00:20:00+02:00")
end

it "calculates the correct time from 2024-04-24 12:00:00 UTC" do
expect(rule.next_time(utc_tz.parse("2024-04-24 12:00:00"), start_time, nil).iso8601).to eq("2024-04-26T00:20:00+03:00")
end

it "calculates the correct time from 2024-04-26 00:20:01 Africa/Cairo" do
expect(rule.next_time(cairo_tz.parse("2024-04-26 00:20:01"), start_time, nil).iso8601).to eq("2024-05-03T00:20:00+03:00")
end
end

describe :realign do
let(:cairo_tz) { ActiveSupport::TimeZone["Africa/Cairo"] }
let(:utc_tz) { ActiveSupport::TimeZone["UTC"] }
let(:start_time) { cairo_tz.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) }

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
end
end
end