Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #245 from avit/issues/245
Fix `occurs_on?` misses when time is near midnight
  • Loading branch information
avit committed Jul 6, 2014
2 parents dafa3f2 + 41ff84a commit a79d498
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 16 deletions.
32 changes: 16 additions & 16 deletions lib/ice_cube/time_util.rb
Expand Up @@ -24,6 +24,18 @@ def self.now(reference=Time.now)
match_zone(Time.at(Time.now.to_i), reference)
end

def self.build_in_zone(args, reference)
if reference.respond_to?(:time_zone)
reference.time_zone.local(*args)
elsif reference.utc?
Time.utc(*args)
elsif reference.zone
Time.local(*args)
else
Time.new(*args << reference.utc_offset)
end
end

def self.match_zone(time, reference)
return unless time = ensure_time(time)
if reference.respond_to? :time_zone
Expand Down Expand Up @@ -96,25 +108,13 @@ def self.restore_deserialized_offset(time, orig_offset_str)
end

# Get the beginning of a date
def self.beginning_of_date(date, reference=nil)
args = [date.year, date.month, date.day, 0, 0, 0]
reference ||= Time.local(*args)
if reference.respond_to?(:time_zone) && reference.time_zone
reference.time_zone.local(*args)
else
match_zone(Time.new(*args << reference.utc_offset), reference)
end
def self.beginning_of_date(date, reference=Time.now)
build_in_zone([date.year, date.month, date.day, 0, 0, 0], reference)
end

# Get the end of a date
def self.end_of_date(date, reference=nil)
args = [date.year, date.month, date.day, 23, 59, 59]
reference ||= Time.local(*args)
if reference.respond_to?(:time_zone) && reference.time_zone
reference.time_zone.local(*args)
else
match_zone(Time.new(*args << reference.utc_offset), reference)
end
def self.end_of_date(date, reference=Time.now)
build_in_zone([date.year, date.month, date.day, 23, 59, 59], reference)
end

# Convert a symbol to a numeric month
Expand Down
8 changes: 8 additions & 0 deletions spec/examples/schedule_spec.rb
Expand Up @@ -713,6 +713,14 @@
include_examples :occurs_on?
end

context 'across DST' do
let(:start_time) { Time.local(2010, 3, 2, 0, 0, 0) }
before { schedule.add_recurrence_rule(IceCube::Rule.monthly) }
it 'determines local midnight with time change' do
schedule.occurs_on?(Date.new(2010, 7, 2)).should be_true
end
end

it 'should be true for multiple rtimes' do
schedule = IceCube::Schedule.new(Time.local(2010, 7, 10, 16))
schedule.add_recurrence_time(Time.local(2010, 7, 11, 16))
Expand Down
41 changes: 41 additions & 0 deletions spec/examples/time_util_spec.rb
Expand Up @@ -3,6 +3,47 @@
module IceCube
describe TimeUtil do

describe :beginning_of_date do

let(:utc_time) { Time.utc(2014, 7, 8, 12, 34, 56) }
let(:dst_time) { Time.local(2014, 7, 8, 12, 34, 56) }
let(:std_time) { Time.local(2014, 1, 1, 12, 34, 56) }

it "returns 00:00:00 crossing into DST" do
time = TimeUtil.beginning_of_date(dst_time.to_date, std_time)
dst_diff = dst_time.utc_offset - std_time.utc_offset
expect([time.hour, time.min, time.sec]).to eq [0, 0, 0]
expect(time.utc_offset - std_time.utc_offset).to eq dst_diff
end

it "returns 00:00:00 crossing out of DST" do
time = TimeUtil.beginning_of_date(std_time.to_date, dst_time)
dst_diff = std_time.utc_offset - dst_time.utc_offset
expect([time.hour, time.min, time.sec]).to eq [0, 0, 0]
expect(time.utc_offset - dst_time.utc_offset).to eq dst_diff
end

it "returns 00:00:00 from UTC for local time" do
time = TimeUtil.beginning_of_date(utc_time.to_date, dst_time)
expect([time.hour, time.min, time.sec]).to eq [0, 0, 0]
expect(time.utc_offset).to eq (dst_time.utc_offset)
end

it "returns 00:00:00 from local time for UTC" do
time = TimeUtil.beginning_of_date(dst_time.to_date, utc_time)
expect([time.hour, time.min, time.sec]).to eq [0, 0, 0]
expect(time.utc?).to eq true
end

it "returns 00:00:00 from local time for nonlocal time" do
time = TimeUtil.beginning_of_date(dst_time.to_date, std_time.getlocal(7200))
zone_diff = dst_time.utc_offset - 7200
expect([time.hour, time.min, time.sec]).to eq [0, 0, 0]
expect(time.utc_offset).to eq 7200
end

end

describe :wday_to_sym do
it 'converts 0..6 to weekday symbols' do
TimeUtil.wday_to_sym(1).should == :monday
Expand Down

0 comments on commit a79d498

Please sign in to comment.