lib/timecop/time_stack_item.rb in timecop-0.3.4.rc1 vs lib/timecop/time_stack_item.rb in timecop-0.3.4.rc2

- old
+ new

@@ -4,74 +4,110 @@ # movements on a simple stack. class TimeStackItem #:nodoc: attr_reader :mock_type def initialize(mock_type, *args) - @mock_type = mock_type - arg = args.shift - if arg.is_a?(Time) - @time = arg.getlocal - elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime) - offset_difference = Time.now_without_mock_time.utc_offset - rational_to_utc_offset(arg.offset) - @time = Time.local(arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec) + offset_difference - elsif Object.const_defined?(:Date) && arg.is_a?(Date) - @time = Time.local(arg.year, arg.month, arg.day, 0, 0, 0) - elsif args.empty? && arg.kind_of?(Integer) - @time = Time.now + arg - else # we'll just assume it's a list of y/m/h/d/m/s - year = arg || 0 - month = args.shift || 1 - day = args.shift || 1 - hour = args.shift || 0 - minute = args.shift || 0 - second = args.shift || 0 - @time = Time.local(year, month, day, hour, minute, second) - end + raise "Unknown mock_type #{mock_type}" unless [:freeze, :travel].include?(mock_type) + @mock_type = mock_type + @time = parse_time(*args) + @travel_offset = compute_travel_offset + @dst_adjustment = compute_dst_adjustment end def year - @time.year + time.year end def month - @time.month + time.month end def day - @time.day + time.day end def hour - @time.hour + time.hour end def min - @time.min + time.min end def sec - @time.sec + time.sec end + def utc_offset + time.utc_offset + end + + def travel_offset + @travel_offset + end + def time #:nodoc: - @time + if travel_offset.nil? + @time + else + Time.now_without_mock_time + travel_offset + end end def date time.send(:to_date) end def datetime - time.send(:to_datetime) + # DateTime doesn't know about DST, so let's remove its presence + our_offset = utc_offset + dst_adjustment + DateTime.new(year, month, day, hour, min, sec, utc_offset_to_rational(our_offset)) 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) + arg = args.shift + if arg.is_a?(Time) + arg.getlocal + elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime) + offset_difference = Time.now.utc_offset - rational_to_utc_offset(arg.offset) + Time.local(arg.year, arg.month, arg.day, arg.hour, arg.min, arg.sec) + offset_difference + elsif Object.const_defined?(:Date) && arg.is_a?(Date) + Time.local(arg.year, arg.month, arg.day, 0, 0, 0) + elsif args.empty? && arg.kind_of?(Integer) + Time.now + arg + else # we'll just assume it's a list of y/m/d/h/m/s + year = arg || 0 + month = args.shift || 1 + day = args.shift || 1 + hour = args.shift || 0 + minute = args.shift || 0 + second = args.shift || 0 + Time.local(year, month, day, hour, minute, second) + end + end + + def compute_dst_adjustment + 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 end end \ No newline at end of file