timecop-0.5.9/0000755000004100000410000000000012073316710013215 5ustar www-datawww-datatimecop-0.5.9/test/0000755000004100000410000000000012073316710014174 5ustar www-datawww-datatimecop-0.5.9/test/run_tests.sh0000705000004100000410000000010712073316710016552 0ustar www-datawww-data#!/bin/sh for f in *_test.rb; do ${RUBY:-ruby} -I../lib:. $f done timecop-0.5.9/test/timecop_test.rb0000604000004100000410000003330312073316710017216 0ustar www-datawww-datarequire 'date' require File.join(File.dirname(__FILE__), "test_helper") require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop') class TestTimecop < Test::Unit::TestCase def teardown Timecop.return end def test_freeze_changes_and_resets_time assert !Time.respond_to?(:zone) || Time.zone.nil? t = Time.local(2008, 10, 10, 10, 10, 10) assert_not_equal t, Time.now Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert_equal t, Time.now end assert_not_equal t, Time.now end def test_freeze_yields_mocked_time Timecop.freeze(2008, 10, 10, 10, 10, 10) do |frozen_time| assert_equal frozen_time, Time.now end end def test_freeze_then_return_unsets_mock_time Timecop.freeze(1) Timecop.return assert_nil Time.send(:mock_time) end def test_travel_then_return_unsets_mock_time Timecop.travel(1) Timecop.return assert_nil Time.send(:mock_time) end def test_freeze_with_block_unsets_mock_time assert_nil Time.send(:mock_time), "test is invalid" Timecop.freeze(1) do; end assert_nil Time.send(:mock_time) end def test_travel_with_block_unsets_mock_time assert_nil Time.send(:mock_time), "test is invalid" Timecop.travel(1) do; end assert_nil Time.send(:mock_time) end def test_travel_does_not_reduce_precision_of_datetime # requires to_r on Float (>= 1.9) if Float.method_defined?(:to_r) Timecop.travel(1) assert_not_equal DateTime.now, DateTime.now end end def test_freeze_in_time_subclass_returns_mocked_subclass t = Time.local(2008, 10, 10, 10, 10, 10) custom_timeklass = Class.new(Time) do def custom_format_method() strftime('%F') end end Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert custom_timeklass.now.is_a? custom_timeklass assert Time.now.eql? custom_timeklass.now assert custom_timeklass.now.respond_to? :custom_format_method end end def test_freeze_in_date_subclass_returns_mocked_subclass t = Time.local(2008, 10, 10, 10, 10, 10) custom_dateklass = Class.new(Date) do def custom_format_method() strftime('%F') end end Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert custom_dateklass.today.is_a? custom_dateklass assert Date.today.eql? custom_dateklass.today assert custom_dateklass.today.respond_to? :custom_format_method end end def test_freeze_in_datetime_subclass_returns_mocked_subclass t = Time.local(2008, 10, 10, 10, 10, 10) custom_datetimeklass = Class.new(DateTime) do def custom_format_method() strftime('%F') end end Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert custom_datetimeklass.now.is_a? custom_datetimeklass assert DateTime.now.eql? custom_datetimeklass.now assert custom_datetimeklass.now.respond_to? :custom_format_method end end def test_recursive_freeze t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert_equal t, Time.now t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.freeze(2008, 9, 9, 9, 9, 9) do assert_equal t2, Time.now end assert_equal t, Time.now end assert_not_equal t, Time.now end def test_freeze_with_time_instance_works_as_expected t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert_equal t, Time.now assert_date_times_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now assert_equal Date.new(2008, 10, 10), Date.today end assert_not_equal t, Time.now assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now assert_not_equal Date.new(2008, 10, 10), Date.today end def test_freeze_with_datetime_on_specific_timezone_during_dst each_timezone do # Start from a time that is subject to DST Timecop.freeze(2009, 9, 1) # Travel to a DateTime that is also in DST t = DateTime.parse("2009-10-11 00:38:00 +0200") Timecop.freeze(t) do assert_date_times_equal t, DateTime.now end Timecop.return end end def test_freeze_with_datetime_on_specific_timezone_not_during_dst each_timezone do # Start from a time that is not subject to DST Timecop.freeze(2009, 12, 1) # Travel to a time that is also not in DST t = DateTime.parse("2009-12-11 00:38:00 +0100") Timecop.freeze(t) do assert_date_times_equal t, DateTime.now end end end def test_freeze_with_datetime_from_a_non_dst_time_to_a_dst_time each_timezone do # Start from a time that is not subject to DST Timecop.freeze(DateTime.parse("2009-12-1 00:00:00 +0100")) # Travel back to a time in DST t = DateTime.parse("2009-10-11 00:38:00 +0200") Timecop.freeze(t) do assert_date_times_equal t, DateTime.now end end end def test_freeze_with_datetime_from_a_dst_time_to_a_non_dst_time each_timezone do # Start from a time that is not subject to DST Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 +0200")) # Travel back to a time in DST t = DateTime.parse("2009-12-1 00:38:00 +0100") Timecop.freeze(t) do assert_date_times_equal t, DateTime.now end end end def test_freeze_with_date_instance_works_as_expected d = Date.new(2008, 10, 10) Timecop.freeze(d) do assert_equal d, Date.today assert_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now assert_date_times_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now end assert_not_equal d, Date.today assert_not_equal Time.local(2008, 10, 10, 0, 0, 0), Time.now assert_not_equal DateTime.new(2008, 10, 10, 0, 0, 0, local_offset), DateTime.now end def test_freeze_with_integer_instance_works_as_expected t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert_equal t, Time.now assert_date_times_equal DateTime.new(2008, 10, 10, 10, 10, 10, local_offset), DateTime.now assert_equal Date.new(2008, 10, 10), Date.today Timecop.freeze(10) do assert_equal t + 10, Time.now assert_equal Time.local(2008, 10, 10, 10, 10, 20), Time.now assert_equal Date.new(2008, 10, 10), Date.today end end assert_not_equal t, Time.now assert_not_equal DateTime.new(2008, 10, 10, 10, 10, 10), DateTime.now assert_not_equal Date.new(2008, 10, 10), Date.today end def test_exception_thrown_in_freeze_block_properly_resets_time t = Time.local(2008, 10, 10, 10, 10, 10) begin Timecop.freeze(t) do assert_equal t, Time.now raise "blah exception" end rescue assert_not_equal t, Time.now assert_nil Time.send(:mock_time) end end def test_freeze_freezes_time t = Time.local(2008, 10, 10, 10, 10, 10) now = Time.now Timecop.freeze(t) do #assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened." new_t, new_d, new_dt = Time.now, Date.today, DateTime.now assert_equal t, new_t, "Failed to freeze time." # 2 seconds #sleep(10) assert_equal new_t, Time.now assert_equal new_d, Date.today assert_equal new_dt, DateTime.now end end def test_travel_keeps_time_moving t = Time.local(2008, 10, 10, 10, 10, 10) now = Time.now Timecop.travel(t) do new_now = Time.now assert_times_effectively_equal(new_now, t, 1, "Looks like we failed to actually travel time") sleep(0.25) assert_times_effectively_not_equal new_now, Time.now, 0.25, "Looks like time is not moving" end end def test_mocked_date_time_now_is_local each_timezone do t = DateTime.parse("2009-10-11 00:38:00 +0200") Timecop.freeze(t) do assert_equal local_offset, DateTime.now.offset, "Failed for timezone: #{ENV['TZ']}" end end end def test_scaling_keeps_time_moving_at_an_accelerated_rate t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.scale(4, t) do start = Time.now assert_times_effectively_equal start, t, 1, "Looks like we failed to actually travel time" sleep(0.25) assert_times_effectively_equal Time.at((start + 4*0.25).to_f), Time.now, 0.25, "Looks like time is not moving at 4x" end end def test_scaling_returns_now_if_no_block_given t = Time.local(2008, 10, 10, 10, 10, 10) assert_times_effectively_equal t, Timecop.scale(4, t) end def test_freeze_with_utc_time each_timezone do t = Time.utc(2008, 10, 10, 10, 10, 10) local = t.getlocal Timecop.freeze(t) do assert_equal local, Time.now, "Failed for timezone: #{ENV['TZ']}" end end end def test_destructive_methods_on_frozen_time # Use any time zone other than UTC. ENV['TZ'] = 'EST' t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert !Time.now.utc?, "Time#local failed to return a time in the local time zone." # #utc, #gmt, and #localtime are destructive methods. Time.now.utc assert !Time.now.utc?, "Failed to thwart destructive methods." end end def test_recursive_travel_maintains_each_context t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.travel(2008, 10, 10, 10, 10, 10) do assert((t - Time.now).abs < 50, "Failed to travel time.") t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.travel(2008, 9, 9, 9, 9, 9) do assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.") assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.") end assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.") end assert_nil Time.send(:mock_time) end def test_recursive_travel_yields_correct_time Timecop.travel(2008, 10, 10, 10, 10, 10) do Timecop.travel(2008, 9, 9, 9, 9, 9) do |inner_freeze| assert_times_effectively_equal inner_freeze, Time.now, 1, "Failed to yield current time back to block" end end end def test_recursive_travel_then_freeze t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.travel(2008, 10, 10, 10, 10, 10) do assert((t - Time.now).abs < 50, "Failed to travel time.") t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.freeze(2008, 9, 9, 9, 9, 9) do assert_equal t2, Time.now end assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.") end assert_nil Time.send(:mock_time) end def test_recursive_freeze_then_travel t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert_equal t, Time.now t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.travel(t2) do assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.") assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.") end assert_equal t, Time.now end assert_nil Time.send(:mock_time) end def test_travel_time_returns_now_if_no_block_given t_future = Time.local(2030, 10, 10, 10, 10, 10) assert_times_effectively_equal t_future, Timecop.travel(t_future) end def test_return_temporarily_returns_to_current_time_in_given_block time_after_travel = Time.local(1990, 7, 16) now = Time.now Timecop.travel(time_after_travel) assert_times_effectively_equal(time_after_travel, Time.now) Timecop.return do assert_times_effectively_equal(now, Time.now) end assert_times_effectively_equal(time_after_travel, Time.now) end def test_travel_time_with_block_returns_the_value_of_the_block t_future = Time.local(2030, 10, 10, 10, 10, 10) expected = :foo actual = Timecop.travel(t_future) { expected } assert_equal expected, actual end def test_freeze_time_returns_now_if_no_block_given t_future = Time.local(2030, 10, 10, 10, 10, 10) assert_times_effectively_equal t_future, Timecop.freeze(t_future) end def test_freeze_time_with_block_returns_the_value_of_the_block t_future = Time.local(2030, 10, 10, 10, 10, 10) expected = :foo actual = Timecop.freeze(t_future) { expected } assert_equal expected, actual end def test_return_returns_nil assert_nil Timecop.return end def test_freeze_without_params Timecop.freeze 1 do current_time = Time.now Timecop.freeze do assert_equal Time.now, current_time end end end def test_freeze_with_new_date date = Date.new(2012, 6, 9) Timecop.freeze(Date.new(2012, 6, 9)) do assert_equal date, Time.now.__send__(:to_date) end end def test_return_to_baseline_without_a_baseline_set_returns_to_current_time time_before_travel = Time.now Timecop.travel Time.now - 60 Timecop.return_to_baseline assert times_effectively_equal(time_before_travel, Time.now) end def test_return_to_baseline_with_a_baseline_set_returns_to_baseline baseline = Time.local(1945, 10, 10, 10, 10, 10) Timecop.baseline = baseline Timecop.travel Time.now - 60 time_now = Timecop.return_to_baseline assert times_effectively_equal(baseline, time_now), "expected to return to #{baseline}, but returned to #{time_now}" end def test_return_eliminates_baseline time_before_travel = Time.now Timecop.baseline = Time.local(1937, 9, 9, 9, 9, 9) Timecop.return assert times_effectively_equal(time_before_travel, Time.now) Timecop.travel(Time.now - 100) Timecop.return_to_baseline assert times_effectively_equal(time_before_travel, Time.now) end def test_mock_time_new_same_as_now date = Time.local(2011, 01, 02) Timecop.freeze date assert_equal date, Time.now assert_equal date, Time.new end def test_not_callable_send_travel assert_raise NoMethodError do Timecop.send_travel(:travel, Time.now - 100) end end end timecop-0.5.9/test/timecop_without_date_test.rb0000604000004100000410000000757112073316710022006 0ustar www-datawww-data require File.join(File.dirname(__FILE__), "test_helper") require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop') class TestTimecopWithoutDate < Test::Unit::TestCase def setup Object.send(:remove_const, :Date) if Object.const_defined?(:Date) Object.send(:remove_const, :DateTime) if Object.const_defined?(:DateTime) end # just in case...let's really make sure that Timecop is disabled between tests... def teardown Timecop.return end def test_freeze_changes_and_resets_time # depending on how we're invoked (individually or via the rake test suite) assert !Time.respond_to?(:zone) || Time.zone.nil? t = Time.local(2008, 10, 10, 10, 10, 10) assert_not_equal t, Time.now Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert_equal t, Time.now end assert_not_equal t, Time.now end def test_recursive_freeze t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(2008, 10, 10, 10, 10, 10) do assert_equal t, Time.now t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.freeze(2008, 9, 9, 9, 9, 9) do assert_equal t2, Time.now end assert_equal t, Time.now end assert_nil Time.send(:mock_time) end def test_exception_thrown_in_freeze_block_properly_resets_time t = Time.local(2008, 10, 10, 10, 10, 10) begin Timecop.freeze(t) do assert_equal t, Time.now raise "blah exception" end rescue assert_not_equal t, Time.now assert_nil Time.send(:mock_time) end end def test_freeze_freezes_time t = Time.local(2008, 10, 10, 10, 10, 10) now = Time.now Timecop.freeze(t) do sleep(0.25) assert Time.now < now, "If we had failed to freeze, time would have proceeded, which is what appears to have happened." new_t = Time.now assert_equal t, new_t, "Failed to change move time." # 2 seconds assert_equal new_t, Time.now end end def test_travel_keeps_time_moving t = Time.local(2008, 10, 10, 10, 10, 10) now = Time.now Timecop.travel(t) do new_now = Time.now assert_times_effectively_equal new_now, t, 1, "Looks like we failed to actually travel time" # 0.1 seconds sleep(0.25) assert_times_effectively_not_equal new_now, Time.now, 0.25, "Looks like time is not moving" end end def test_recursive_travel_maintains_each_context t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.travel(2008, 10, 10, 10, 10, 10) do assert((t - Time.now).abs < 50, "Failed to travel time.") t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.travel(2008, 9, 9, 9, 9, 9) do assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.") assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.") end assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.") end assert_nil Time.send(:mock_time) end def test_recursive_travel_then_freeze t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.travel(2008, 10, 10, 10, 10, 10) do assert((t - Time.now).abs < 50, "Failed to travel time.") t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.freeze(2008, 9, 9, 9, 9, 9) do assert_equal t2, Time.now end assert_times_effectively_equal(t, Time.now, 2, "Failed to restore previously-traveled time.") end assert_nil Time.send(:mock_time) end def test_recursive_freeze_then_travel t = Time.local(2008, 10, 10, 10, 10, 10) Timecop.freeze(t) do assert_equal t, Time.now t2 = Time.local(2008, 9, 9, 9, 9, 9) Timecop.travel(t2) do assert_times_effectively_equal(t2, Time.now, 1, "Failed to travel time.") assert_times_effectively_not_equal(t, Time.now, 1000, "Failed to travel time.") end assert_equal t, Time.now end assert_nil Time.send(:mock_time) end end timecop-0.5.9/test/test_helper.rb0000604000004100000410000000266612073316710017045 0ustar www-datawww-datarequire 'rubygems' require 'bundler/setup' require 'test/unit' begin require 'mocha/setup' rescue LoadError require 'mocha' end class Test::Unit::TestCase private # Tests to see that two times are within the given distance, # in seconds, from each other. def times_effectively_equal(time1, time2, seconds_interval = 1) (time1 - time2).abs <= seconds_interval end def assert_times_effectively_equal(time1, time2, seconds_interval = 1, msg = nil) assert times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}" end def assert_times_effectively_not_equal(time1, time2, seconds_interval = 1, msg = nil) assert !times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}" end def local_offset DateTime.now_without_mock_time.offset end TIMEZONES = ["Europe/Paris", "UTC", "EDT"] def each_timezone old_tz = ENV["TZ"] begin TIMEZONES.each do |timezone| ENV["TZ"] = timezone yield end ensure ENV["TZ"] = old_tz end end def a_time_stack_item Timecop::TimeStackItem.new(:freeze, 2008, 1, 1, 0, 0, 0) end def assert_date_times_equal(dt1, dt2) assert_equal dt1, dt2, "Failed for timezone: #{ENV['TZ']}: #{dt1.to_s} not equal to #{dt2.to_s}" end end timecop-0.5.9/test/timecop_without_date_but_with_time_test.rb0000604000004100000410000000047512073316710024725 0ustar www-datawww-datarequire "test/unit" class TestTimecopWithoutDateButWithTime < Test::Unit::TestCase TIMECOP_LIB = File.join(File.dirname(__FILE__), '..', 'lib', 'timecop') def test_loads_properly_when_time_is_required_instead_of_date assert_nothing_raised do require "time" require TIMECOP_LIB end end end timecop-0.5.9/test/time_stack_item_test.rb0000604000004100000410000002031712073316710020720 0ustar www-datawww-datarequire 'date' require File.join(File.dirname(__FILE__), "test_helper") require File.join(File.dirname(__FILE__), '..', 'lib', 'timecop') class TestTimeStackItem < Test::Unit::TestCase def teardown Timecop.active_support = nil Timecop.return end def test_new_with_time t = Time.now y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec stack_item = Timecop::TimeStackItem.new(:freeze, t) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_new_with_time_and_arguments t = Time.new(2012, 7, 28, 20, 0) y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec stack_item = Timecop::TimeStackItem.new(:freeze, t) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_new_with_datetime_now t = DateTime.now y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec stack_item = Timecop::TimeStackItem.new(:freeze, t) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_new_with_datetime_in_different_timezone each_timezone do t = DateTime.parse("2009-10-11 00:38:00 +0200") stack_item = Timecop::TimeStackItem.new(:freeze, t) assert_date_times_equal(t, stack_item.datetime) end end def test_new_with_date date = Date.today y, m, d, h, min, s = date.year, date.month, date.day, 0, 0, 0 stack_item = Timecop::TimeStackItem.new(:freeze, date) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end # Due to the nature of this test (calling Time.now once in this test and # once in #new), this test may fail when two subsequent calls # to Time.now return a different second. def test_new_with_integer t = Time.now y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec stack_item = Timecop::TimeStackItem.new(:freeze, 0) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_new_with_individual_arguments y, m, d, h, min, s = 2008, 10, 10, 10, 10, 10 stack_item = Timecop::TimeStackItem.new(:freeze, y, m, d, h, min, s) assert_equal y, stack_item.year assert_equal m, stack_item.month assert_equal d, stack_item.day assert_equal h, stack_item.hour assert_equal min, stack_item.min assert_equal s, stack_item.sec end def test_rational_to_utc_offset assert_equal -14400, a_time_stack_item.send(:rational_to_utc_offset, Rational(-1, 6)) assert_equal -18000, a_time_stack_item.send(:rational_to_utc_offset, Rational(-5, 24)) assert_equal 0, a_time_stack_item.send(:rational_to_utc_offset, Rational(0, 1)) assert_equal 3600, a_time_stack_item.send(:rational_to_utc_offset, Rational(1, 24)) end def test_utc_offset_to_rational assert_equal Rational(-1, 6), a_time_stack_item.send(:utc_offset_to_rational, -14400) assert_equal Rational(-5, 24), a_time_stack_item.send(:utc_offset_to_rational, -18000) assert_equal Rational(0, 1), a_time_stack_item.send(:utc_offset_to_rational, 0) assert_equal Rational(1, 24), a_time_stack_item.send(:utc_offset_to_rational, 3600) end def test_compute_dst_adjustment_for_dst_to_dst Timecop.freeze(DateTime.parse("2009-10-1 00:38:00 -0400")) t = DateTime.parse("2009-10-11 00:00:00 -0400") tsi = Timecop::TimeStackItem.new(:freeze, t) return if !(Time.now.dst? && tsi.time.dst?) assert_equal 0, tsi.send(:dst_adjustment) end def test_compute_dst_adjustment_for_non_dst_to_non_dst Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0400")) t = DateTime.parse("2009-12-11 00:00:00 -0400") tsi = Timecop::TimeStackItem.new(:freeze, t) return if Time.now.dst? || tsi.time.dst? assert_equal 0, tsi.send(:dst_adjustment) end def test_compute_dst_adjustment_for_dst_to_non_dst Timecop.freeze(DateTime.parse("2009-10-1 00:38:00 -0400")) t = DateTime.parse("2009-12-11 00:00:00 -0400") tsi = Timecop::TimeStackItem.new(:freeze, t) return if !Time.now.dst? || tsi.time.dst? assert_equal 60 * 60, tsi.send(:dst_adjustment) end def test_compute_dst_adjustment_for_non_dst_to_dst Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0400")) t = DateTime.parse("2009-10-11 00:00:00 -0400") tsi = Timecop::TimeStackItem.new(:freeze, t) return if Time.now.dst? || !tsi.time.dst? assert_equal -1 * 60 * 60, tsi.send(:dst_adjustment) end # Ensure DateTimes handle changing DST properly def test_datetime_for_dst_to_non_dst Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500")) t = DateTime.parse("2009-10-11 00:00:00 -0400") tsi = Timecop::TimeStackItem.new(:freeze, t) assert_date_times_equal t, tsi.datetime end def test_datetime_for_non_dst_to_dst Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 -0400")) t = DateTime.parse("2009-11-30 23:38:00 -0500") tsi = Timecop::TimeStackItem.new(:freeze, t) return if !tsi.time.dst? assert_date_times_equal t, tsi.datetime assert_equal Date.new(2009, 12, 1), tsi.date end def test_set_travel_offset_for_travel t_now = Time.now t = Time.local(2009, 10, 1, 0, 0, 30) expected_offset = t - t_now tsi = Timecop::TimeStackItem.new(:travel, t) assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly" end def test_set_travel_offset_for_freeze Timecop.freeze(2009, 10, 1, 0, 0, 0) t = Time.local(2009, 10, 1, 0, 0, 30) tsi = Timecop::TimeStackItem.new(:freeze, t) assert_equal nil, tsi.send(:travel_offset) end def test_timezones require 'active_support/all' Time.zone = "Europe/Zurich" time = Time.zone.parse("2012-12-27T12:12:12+08:00") Timecop.freeze(time) do |frozen_time| assert_equal time, frozen_time end end def test_set_scaling_factor_for_scale t_now = Time.now t = Time.local(2009, 10, 1, 0, 0, 30) expected_offset = t - t_now tsi = Timecop::TimeStackItem.new(:scale, 4, t) assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly" assert_equal tsi.send(:scaling_factor), 4, "Scaling factor not set" end def test_parse_string_date_with_active_support date = '2012-01-02' Time.expects(:parse).with(date).returns(Time.local(2012, 01, 02)) Timecop.freeze(date) end def test_parse_only_string_with_active_support Time.expects(:parse).never Timecop.freeze(2011, 01, 02, hour=0, minute=0, second=0) end def test_parse_with_active_support_off date = '2012-01-02' Timecop.active_support = false Time.expects(:parse).never Timecop.freeze(date) end def test_uses_active_supports_in_time_zone time = Time.now Time.any_instance.expects(:in_time_zone).returns(time) Timecop::TimeStackItem.new(:freeze, time) end def test_configured_off_active_support_in_time_zone_xxx Timecop.active_support = false Time.any_instance.expects(:in_time_zone).never Timecop::TimeStackItem.new(:freeze, Time.now) end def test_parse_date assert_nothing_raised do Timecop.freeze(Date.new(2012, 6, 9)) end end def test_nsecs_are_set time = Time.now Timecop.freeze time assert_equal time, Time.now assert_equal time.nsec, Time.now.nsec if (Time.now.respond_to?(:nsec)) end def test_time_with_different_timezone require 'active_support/all' Time.zone = "Tokyo" t = Time.now Timecop.freeze(t) do assert_times_effectively_equal t, Time.now end end end timecop-0.5.9/LICENSE0000604000004100000410000000211012073316710014210 0ustar www-datawww-data(The MIT License) Copyright (c) 2012 — Travis Jeffery, John Trupiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. timecop-0.5.9/Rakefile0000604000004100000410000000112512073316710014655 0ustar www-datawww-datarequire 'bundler/setup' require 'bundler/gem_tasks' require 'rake/testtask' require 'rdoc/task' $LOAD_PATH.unshift("lib") Rake::RDocTask.new do |rdoc| if File.exist?('VERSION') version = File.read('VERSION') else version = "" end rdoc.rdoc_dir = 'rdoc' rdoc.options << '--line-numbers' << '--inline-source' rdoc.title = "timecop #{version}" rdoc.rdoc_files.include('README*') rdoc.rdoc_files.include('History.rdoc') rdoc.rdoc_files.include('lib/**/*.rb') end task :test do system "cd test && ./run_tests.sh" end desc 'Default: run tests' task :default => [:test] timecop-0.5.9/README.markdown0000604000004100000410000001105512073316710015714 0ustar www-datawww-data# timecop [![Build Status](https://secure.travis-ci.org/travisjeffery/timecop.png)](http://travis-ci.org/travisjeffery/timecop) - Source[http://github.com/travisjeffery/timecop] - Documentation[http://johntrupiano.rubyforge.org/timecop] ## DESCRIPTION A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call. ## INSTALL gem install timecop ## FEATURES - Freeze time to a specific point. - Travel back to a specific point in time, but allow time to continue moving forward from there. - Scale time by a given scaling factor that will cause time to move at an accelerated pace. - No dependencies, can be used with _any_ ruby project - Timecop api allows arguments to be passed into #freeze and #travel as one of the following: - Time instance - DateTime instance - Date instance - individual arguments (year, month, day, hour, minute, second) - a single integer argument that is interpreted as an offset in seconds from Time.now - Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain its interpretation of now. - Works with regular Ruby projects, and Ruby on Rails projects ## USAGE Run a time-sensitive test ```ruby joe = User.find(1) joe.purchase_home() assert !joe.mortgage_due? # move ahead a month and assert that the mortgage is due Timecop.freeze(Date.today + 30) do assert joe.mortgage_due? end ``` You can mock the time for a set of tests easily via setup/teardown methods ```ruby describe "some set of tests to mock" do before do Timecop.freeze(Time.local(1990)) end after do Timecop.return end it "should do blah blah blah" {} end ``` Set the time for the test environment of a rails app -- this is particularly helpful if your whole application is time-sensitive. It allows you to build your test data at a single point in time, and to move in/out of that time as appropriate (within your tests) in config/environments/test.rb ```ruby config.after_initialize do # Set Time.now to September 1, 2008 10:05:00 AM (at this instant), but allow it to move forward t = Time.local(2008, 9, 1, 10, 5, 0) Timecop.travel(t) end ``` ### The difference between Timecop.freeze and Timecop.travel freeze is used to statically mock the concept of now. As your program executes, Time.now will not change unless you make subsequent calls into the Timecop API. travel, on the other hand, computes an offset between what we currently think Time.now is (recall that we support nested traveling) and the time passed in. It uses this offset to simulate the passage of time. To demonstrate, consider the following code snippets: ```ruby new_time = Time.local(2008, 9, 1, 12, 0, 0) Timecop.freeze(new_time) sleep(10) new_time == Time.now # ==> true Timecop.return # "turn off" Timecop Timecop.travel(new_time) sleep(10) new_time == Time.now # ==> false ``` ### Timecop.scale Let's say you want to test a "live" integration wherein entire days could pass by in minutes while you're able to simulate "real" activity. For example, one such use case is being able to test reports and invoices that run in 30 day cycles in very little time, while also being able to simulate activity via subsequent calls to your application. ```ruby # seconds will now seem like hours Timecop.scale(3600) Time.now # => 2012-09-20 21:23:25 -0500 # seconds later, hours have past it's gone from 9pm at night to 6am in the morning Time.now # => 2012-09-21 06:22:59 -0500 ``` See #42 for more information, thanks to Ken Mayer, David Holcomb, and Pivotal Labs. ## REFERENCES * {0.3.4 release}[http://blog.smartlogicsolutions.com/2009/12/07/timecop-0-3-4-released/] * {0.3.0 release}[http://blog.smartlogicsolutions.com/2009/09/20/timecop-0-3-0-released/] * {0.2.0 release}[http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/] * {0.1.0 release}[http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/] ## Contribute timecop is maintained by [travisjeffery](http://github.com/travisjeffery), and was created by [jtrupiano](https://github.com/jtrupiano). Here's the most direct way to get your work merged into the project. - Fork the project - Clone down your fork - Create a feature branch - Hack away and add tests, not necessarily in that order - Make sure everything still passes by running tests - If necessary, rebase your commits into logical chunks without errors - Push the branch up to your fork - Send a pull request for your branch timecop-0.5.9/metadata.yml0000644000004100000410000000363612073316710015530 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: timecop version: !ruby/object:Gem::Version prerelease: version: 0.5.9 platform: ruby authors: - Travis Jeffery - John Trupiano autorequire: bindir: bin cert_chain: [] date: 2013-01-09 00:00:00.000000000 Z dependencies: [] description: A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call. email: travisjeffery@gmail.com executables: [] extensions: [] extra_rdoc_files: - LICENSE - README.markdown files: - History.rdoc - LICENSE - README.markdown - Rakefile - lib/timecop.rb - lib/timecop/time_extensions.rb - lib/timecop/time_stack_item.rb - lib/timecop/version.rb - lib/timecop/timecop.rb - test/run_tests.sh - test/test_helper.rb - test/time_stack_item_test.rb - test/timecop_test.rb - test/timecop_without_date_test.rb - test/timecop_without_date_but_with_time_test.rb homepage: https://github.com/travisjeffery/timecop licenses: [] post_install_message: rdoc_options: - "--charset=UTF-8" require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: !binary |- MA== none: false required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: !binary |- MA== none: false requirements: [] rubyforge_project: timecop rubygems_version: 1.8.24 signing_key: specification_version: 3 summary: A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code. It provides a unified method to mock Time.now, Date.today, and DateTime.now in a single call. test_files: - test/test_helper.rb - test/time_stack_item_test.rb - test/timecop_test.rb - test/timecop_without_date_test.rb - test/timecop_without_date_but_with_time_test.rb timecop-0.5.9/History.rdoc0000604000004100000410000001137712073316710015534 0ustar www-datawww-data=== 0.5.4 / 2012-11-29 * Maintenance * Fix usage with Ruby 1.8 === 0.5.2 / 2012-09-20 * Feature * Timecop#scale, ability to accelerate time by a given scaling factor === 0.5.0 / 2012-09-12 * Maintenance * Timecop#travel, Timecop#freeze blocks return nil or block value === 0.4.6 / 2012-09-05 * Maintenance * Fix rounding support for Ruby < 1.9 === 0.4.5 / 2012-08-09 * Maintenance * Subclasses of Time/Date/DateTime now return proper instances === 0.4.4 / 2012-07-29 * Maintenance * Can now configure Timecop to not use ActiveSupport by setting Timecop.active_support = false === 0.4.3 / 2012-07-27 * Maintenance * Fix alias of Time#new/Time#now when Time#new given with args === 0.4.2 / 2012-07-27 * Maintenance * Mock Time#new the same as Time#now since they're synonyms * Set default arg in parsing to 2000 * Time.freeze defaults to Time#now * Use Time#parse is available to parse Time's given as strings * Add ActiveSupport Time.zone support * Stop DateTime from losing precision after traveling === 0.3.5 / 2010-06-07 * Maintenance * Return a cloned time instance in order to support the destructive methods #gmt, #utc and #localtime * Don't use full path requires where unnecessary === 0.3.4 / 2009-12-07 * Maintenance * Fix various timezone-related issues. Notably, when traveling to a DateTime instance specified in a non-local timezone, convert provided DateTime instance to a local instance and return that from DateTime.now. Code contributed by Michaël Witrant [piglop] * Fix bug that would not allow Timecop to be used when Ruby's 'date' library had not been previously loaded. Code contributed by Tuomas Kareinen [tuomas] * Fix bug when traveling to a DateTime across a DST boundary that resulted in DateTime's being off by an hour. * Migrate argument parsing into Timecop::TimeStackItem to reduce the responsibility of the Timecop class. === 0.3.3 2009-10-30 * Revoked due to regression. === 0.3.2 / 2009-10-24 * Revoked due to regression. === 0.3.1 / 2009-09-30 * Maintenance * DRY up the Timecop class internals. === 0.3.0 / 2009-09-20 * API * Completely remove Timecop#unset_all (deprecated by Timecop#return in 0.2.0) * Return Time.now from #freeze, #travel and #return -- code contributed by Keith Bennett [keithrbennett] * Maintenance * Fix bug that left Time#mock_time set in some instances * Upped build dependency to jeweler ~> 1.2.1 * Don't pollute top-level namespace with classes/constants * Documentation * Clearer examples in the README, better description in the gemspec * Improve RDoc === 0.2.1 / 2009-03-06 * API Changes * Introduced a 5th style of arguments to be passed into #travel and #freeze. Now, if you pass in a single integer value, it will be interpreted as a relative offset in seconds from the current Time.now. Previously this was interpreted as only the year, similar to calling Time.local(2008) --> Jan. 1, 2008. This is no longer the case. * Documentation * Moved to Textile for the README. * Added documentation for the new feature, and fixed a few typos. === 0.2.0 / 2008-12-23 * API Changes * Timecop#travel no longer freezes time. Rather, it computes the current offset between the new "now" and the real "now", and returns times as if Time had continued to move forward * Timecop#freeze now behaves exactly as the old Timecop#travel behaved. Unless you depended on the actual freezing of time (which I think would be rare), you should be able to continue to use #travel without worry. * Timecop#return is now exposed (previously Timecop#unset_all, but not well advertised). It will completely unmock time, and will probably be rarely used outside of the actual implementation of this library. * More Test Coverage * Tests now explicitly cover the cases when the Date and DateTime objects are not loaded, and ensures proper functionality in their absence and existence. * Still haven't done regression testing against anything other than a few version of 1.8.6 (including REE). We should probably try to get this tested on both 1.8.7 and 1.9.1. * Documentation * Fixed up a lot of the poorly-formatted rdoc syntax. The public API should now be properly published in the rdoc, and the internals are omitted. === 0.1.0 / 2008-11-09 * Initial Feature Set * Temporarily (or permanently if you prefer) change the concept of Time.now, DateTime.now (if defined), and Date.today (if defined) * Timecop#travel api allows an argument to be passed in as one of: 1) Time instance, 2) DateTime instance, 3) Date instance, 4) individual arguments (year, month, day, hour, minute, second) * Nested calls to Timecop#travel are supported -- each block will maintain it's interpretation of now. timecop-0.5.9/lib/0000755000004100000410000000000012073316710013763 5ustar www-datawww-datatimecop-0.5.9/lib/timecop.rb0000604000004100000410000000020012073316710015734 0ustar www-datawww-datarequire File.join(File.dirname(__FILE__), "timecop", "timecop") require File.join(File.dirname(__FILE__), "timecop", "version") timecop-0.5.9/lib/timecop/0000755000004100000410000000000012073316710015423 5ustar www-datawww-datatimecop-0.5.9/lib/timecop/version.rb0000604000004100000410000000004612073316710017431 0ustar www-datawww-dataclass Timecop VERSION = "0.5.9" end timecop-0.5.9/lib/timecop/time_extensions.rb0000604000004100000410000000360012073316710021160 0ustar www-datawww-data class Time #:nodoc: class << self def mock_time mocked_time_stack_item = Timecop.top_stack_item mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.time(self) end alias_method :now_without_mock_time, :now def now_with_mock_time mock_time || now_without_mock_time end alias_method :now, :now_with_mock_time alias_method :new_without_mock_time, :new def new_with_mock_time(*args) begin raise ArgumentError.new if args.size <= 0 new_without_mock_time(*args) rescue ArgumentError now end end alias_method :new, :new_with_mock_time end end if Object.const_defined?(:Date) && Date.respond_to?(:today) class Date #:nodoc: class << self def mock_date mocked_time_stack_item = Timecop.top_stack_item mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.date(self) end alias_method :today_without_mock_date, :today def today_with_mock_date mock_date || today_without_mock_date end alias_method :today, :today_with_mock_date end end end if Object.const_defined?(:DateTime) && DateTime.respond_to?(:now) class DateTime #:nodoc: class << self def mock_time mocked_time_stack_item = Timecop.top_stack_item mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime(self) end def now_without_mock_time Time.now_without_mock_time.to_datetime end def now_with_mock_time mock_time || now_without_mock_time end alias_method :now, :now_with_mock_time end end # for ruby1.8 unless Time::public_instance_methods.include? :to_datetime class DateTime class << self def now_without_mock_time Time.now_without_mock_time.send(:to_datetime) end end end end end timecop-0.5.9/lib/timecop/timecop.rb0000604000004100000410000001175712073316710017417 0ustar www-datawww-datarequire 'singleton' require File.join(File.dirname(__FILE__), "time_extensions") require File.join(File.dirname(__FILE__), "time_stack_item") # Timecop # * Wrapper class for manipulating the extensions to the Time, Date, and DateTime objects # * Allows us to "freeze" time in our Ruby applications. # * Optionally allows time travel to simulate a running clock, such time is not technically frozen. # # This is very useful when your app's functionality is dependent on time (e.g. # anything that might expire). This will allow us to alter the return value of # Date.today, Time.now, and DateTime.now, such that our application code _never_ has to change. class Timecop include Singleton class << self attr_accessor :active_support # Allows you to run a block of code and "fake" a time throughout the execution of that block. # This is particularly useful for writing test methods where the passage of time is critical to the business # logic being tested. For example: # # joe = User.find(1) # joe.purchase_home() # assert !joe.mortgage_due? # Timecop.freeze(2008, 10, 5) do # assert joe.mortgage_due? # end # # freeze and travel will respond to several different arguments: # 1. Timecop.freeze(time_inst) # 2. Timecop.freeze(datetime_inst) # 3. Timecop.freeze(date_inst) # 4. Timecop.freeze(offset_in_seconds) # 5. Timecop.freeze(year, month, day, hour=0, minute=0, second=0) # # When a block is also passed, Time.now, DateTime.now and Date.today are all reset to their # previous values after the block has finished executing. This allows us to nest multiple # calls to Timecop.travel and have each block maintain it's concept of "now." # # * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if # benchmark or other timing calls are executed, which implicitly expect Time to actually move # forward. # # * Rails Users: Be especially careful when setting this in your development environment in a # rails project. Generators will load your environment, including the migration generator, # which will lead to files being generated with the timestamp set by the Timecop.freeze call # in your dev environment # # Returns the value of the block if one is given, or the mocked time. def freeze(*args, &block) send_travel(:freeze, *args, &block) end # Allows you to run a block of code and "fake" a time throughout the execution of that block. # See Timecop#freeze for a sample of how to use (same exact usage syntax) # # * Note: Timecop.travel will not freeze time (as opposed to Timecop.freeze). This is a particularly # good candidate for use in environment files in rails projects. # # Returns the value of the block if one is given, or the mocked time. def travel(*args, &block) send_travel(:travel, *args, &block) end # Allows you to run a block of code and "scale" a time throughout the execution of that block. # The first argument is a scaling factor, for example: # Timecop.scale(2) do # ... time will 'go' twice as fast here # end # See Timecop#freeze for exact usage of the other arguments # # Returns the value of the block if one is given, or the mocked time. def scale(*args, &block) send_travel(:scale, *args, &block) end def baseline instance.send(:baseline) end def baseline=(baseline) instance.send(:baseline=, baseline) end # Reverts back to system's Time.now, Date.today and DateTime.now (if it exists) permamently when # no block argument is given, or temporarily reverts back to the system's time temporarily for # the given block. def return(&block) if block_given? instance.send(:return, &block) else instance.send(:unmock!) nil end end def return_to_baseline instance.send(:return_to_baseline) Time.now end def top_stack_item #:nodoc: instance.instance_variable_get(:@_stack).last end private def send_travel(mock_type, *args, &block) val = instance.send(:travel, mock_type, *args, &block) block_given? ? val : Time.now end end private def baseline=(baseline) @baseline = baseline @_stack << TimeStackItem.new(:travel, baseline) end def initialize #:nodoc: @_stack = [] end def travel(mock_type, *args, &block) #:nodoc: stack_item = TimeStackItem.new(mock_type, *args) @_stack << stack_item if block_given? begin yield stack_item.time ensure @_stack.pop end end end def return(&block) current_stack = @_stack current_baseline = @baseline unmock! yield @_stack = current_stack @baseline = current_baseline end def unmock! #:nodoc: @baseline = nil @_stack = [] end def return_to_baseline if @baseline @_stack = [@_stack.shift] else unmock! end end end timecop-0.5.9/lib/timecop/time_stack_item.rb0000604000004100000410000001064412073316710021112 0ustar www-datawww-dataclass Timecop # A data class for carrying around "time movement" objects. Makes it easy to keep track of the time # movements on a simple stack. class TimeStackItem #:nodoc: attr_reader :mock_type def initialize(mock_type, *args) raise "Unknown mock_type #{mock_type}" unless [:freeze, :travel, :scale].include?(mock_type) @scaling_factor = args.shift if mock_type == :scale @mock_type = mock_type @time = parse_time(*args) @time_was = Time.now_without_mock_time @travel_offset = compute_travel_offset @dst_adjustment = compute_dst_adjustment(@time) end def year time.year end def month time.month end def day time.day end def hour time.hour end def min time.min end def sec time.sec end def utc_offset time.utc_offset end def travel_offset @travel_offset end def scaling_factor @scaling_factor end def time(time_klass = Time) #:nodoc: begin actual_time = time_klass.at(@time) calculated_time = time_klass.at(@time.to_f) time = times_are_equal_within_epsilon(actual_time, calculated_time, 1) ? actual_time : calculated_time rescue time = time_klass.at(@time.to_f) end if travel_offset.nil? time elsif scaling_factor.nil? time_klass.at(Time.now_without_mock_time + travel_offset) else time_klass.at(scaled_time) end end def scaled_time (@time + (Time.now_without_mock_time - @time_was) * scaling_factor).to_f end def date(date_klass = Date) date_klass.jd(time.__send__(:to_date).jd) end def datetime(datetime_klass = DateTime) our_offset = utc_offset + dst_adjustment if Float.method_defined?(:to_r) fractions_of_a_second = time.to_f % 1 datetime_klass.new(year, month, day, hour, min, sec + fractions_of_a_second, utc_offset_to_rational(our_offset)) else our_offset = utc_offset + dst_adjustment datetime_klass.new(year, month, day, hour, min, sec, utc_offset_to_rational(our_offset)) end end def dst_adjustment @dst_adjustment end private def rational_to_utc_offset(rational) ((24.0 / rational.denominator) * rational.numerator) * (60 * 60) end def utc_offset_to_rational(utc_offset) Rational(utc_offset, 24 * 60 * 60) end def parse_time(*args) time_klass = Time.respond_to?(:zone) && Time.zone ? Time.zone : Time arg = args.shift if arg.is_a?(Time) if Timecop.active_support != false && arg.respond_to?(:in_time_zone) arg.in_time_zone else arg.getlocal end elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime) expected_time = time_klass.local(arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec) expected_time += expected_time.utc_offset - rational_to_utc_offset(arg.offset) expected_time + compute_dst_adjustment(expected_time) elsif Object.const_defined?(:Date) && arg.is_a?(Date) time_klass.local(arg.year, arg.month, arg.day, 0, 0, 0) elsif args.empty? && arg.kind_of?(Integer) Time.now + arg elsif arg.nil? Time.now else if arg.is_a?(String) && Timecop.active_support != false && Time.respond_to?(:parse) Time.parse(arg) else # we'll just assume it's a list of y/m/d/h/m/s year = arg || 2000 month = args.shift || 1 day = args.shift || 1 hour = args.shift || 0 minute = args.shift || 0 second = args.shift || 0 time_klass.local(year, month, day, hour, minute, second) end end end def compute_dst_adjustment(time) return 0 if !(time.dst? ^ Time.now.dst?) return -1 * 60 * 60 if time.dst? return 60 * 60 end def compute_travel_offset return nil if mock_type == :freeze time - Time.now_without_mock_time end def times_are_equal_within_epsilon t1, t2, epsilon_in_seconds (t1 - t2).abs < epsilon_in_seconds end end end