timecop 0.6.1 → 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +1 -1
- data/README.markdown +31 -16
- data/Rakefile +10 -4
- data/lib/timecop/time_extensions.rb +120 -47
- data/lib/timecop/time_stack_item.rb +109 -127
- data/lib/timecop/timecop.rb +104 -24
- data/lib/timecop/version.rb +1 -1
- data/test/test_helper.rb +26 -21
- data/test/time_stack_item_test.rb +98 -74
- data/test/timecop_test.rb +215 -31
- data/test/timecop_without_date_but_with_time_test.rb +4 -8
- data/test/timecop_without_date_test.rb +22 -23
- metadata +13 -17
- data/test/run_tests.sh +0 -6
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c86a01ea95f5019cb15a6a66c5668e68e7f1e293ca14b910a10cbe1cdd70d668
|
4
|
+
data.tar.gz: e5c6987d3a452fa9ead841021f93bf4ea6bac713c1f6cea38cfc1c1d49baf6ee
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4abbcd2d37b9fdf6dfb1ed1f63f945a882cd62a47ae2ae237da003ccac0bc660572be0800933ea484fb1632707bdc2de457b96f9aad8a62b1dfd96d766220692
|
7
|
+
data.tar.gz: a19cc9026478a29161a832454edebf76105d56d3841575af71e9dbaa305a40a68af285d17b7473369ae913e463cadd7b67ab2e099d13d3162b713d2c3cd87d05
|
data/LICENSE
CHANGED
data/README.markdown
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
# timecop
|
2
2
|
|
3
|
-
[![
|
4
|
-
|
5
|
-
- Source[http://github.com/travisjeffery/timecop]
|
6
|
-
- Documentation[http://johntrupiano.rubyforge.org/timecop]
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/timecop.svg)](https://rubygems.org/gems/timecop)
|
4
|
+
[![Build Status](https://github.com/travisjeffery/timecop/workflows/CI/badge.svg)](https://github.com/travisjeffery/timecop/actions?query=workflow%3ACI)
|
7
5
|
|
8
6
|
## DESCRIPTION
|
9
7
|
|
@@ -11,7 +9,7 @@ A gem providing "time travel" and "time freezing" capabilities, making it dead s
|
|
11
9
|
|
12
10
|
## INSTALL
|
13
11
|
|
14
|
-
|
12
|
+
`bundle add timecop`
|
15
13
|
|
16
14
|
## FEATURES
|
17
15
|
|
@@ -49,12 +47,13 @@ describe "some set of tests to mock" do
|
|
49
47
|
before do
|
50
48
|
Timecop.freeze(Time.local(1990))
|
51
49
|
end
|
52
|
-
|
50
|
+
|
53
51
|
after do
|
54
52
|
Timecop.return
|
55
53
|
end
|
56
54
|
|
57
|
-
it "should do blah blah blah"
|
55
|
+
it "should do blah blah blah" do
|
56
|
+
end
|
58
57
|
end
|
59
58
|
```
|
60
59
|
|
@@ -62,7 +61,7 @@ Set the time for the test environment of a rails app -- this is particularly
|
|
62
61
|
helpful if your whole application is time-sensitive. It allows you to build
|
63
62
|
your test data at a single point in time, and to move in/out of that time as
|
64
63
|
appropriate (within your tests)
|
65
|
-
|
64
|
+
|
66
65
|
in config/environments/test.rb
|
67
66
|
|
68
67
|
```ruby
|
@@ -106,24 +105,40 @@ being able to simulate activity via subsequent calls to your application.
|
|
106
105
|
Timecop.scale(3600)
|
107
106
|
Time.now
|
108
107
|
# => 2012-09-20 21:23:25 -0500
|
109
|
-
# seconds later, hours have
|
108
|
+
# seconds later, hours have passed and it's gone from 9pm at night to 6am in the morning
|
110
109
|
Time.now
|
111
110
|
# => 2012-09-21 06:22:59 -0500
|
112
111
|
```
|
113
112
|
|
114
|
-
See #42 for more information, thanks to Ken Mayer, David Holcomb, and Pivotal Labs.
|
113
|
+
See [#42](https://github.com/travisjeffery/timecop/pull/42) for more information, thanks to Ken Mayer, David Holcomb, and Pivotal Labs.
|
114
|
+
|
115
|
+
### Timecop.safe_mode
|
116
|
+
|
117
|
+
Safe mode forces you to use Timecop with the block syntax since it always puts time back the way it was. If you are running in safe mode and use Timecop without the block syntax `Timecop::SafeModeException` will be raised to tell the user they are not being safe.
|
118
|
+
|
119
|
+
``` ruby
|
120
|
+
# turn on safe mode
|
121
|
+
Timecop.safe_mode = true
|
122
|
+
|
123
|
+
# check if you are in safe mode
|
124
|
+
Timecop.safe_mode?
|
125
|
+
# => true
|
126
|
+
|
127
|
+
# using method without block
|
128
|
+
Timecop.freeze
|
129
|
+
# => Timecop::SafeModeException: Safe mode is enabled, only calls passing a block are allowed.
|
130
|
+
```
|
131
|
+
|
132
|
+
### Rails v Ruby Date/Time libraries
|
115
133
|
|
116
|
-
|
134
|
+
Sometimes [Rails Date/Time methods don't play nicely with Ruby Date/Time methods.](https://rails.lighthouseapp.com/projects/8994/tickets/6410-dateyesterday-datetoday)
|
117
135
|
|
118
|
-
|
119
|
-
* {0.3.0 release}[http://blog.smartlogicsolutions.com/2009/09/20/timecop-0-3-0-released/]
|
120
|
-
* {0.2.0 release}[http://blog.smartlogicsolutions.com/2008/12/24/timecop-2-released-freeze-and-rebase-time-ruby/]
|
121
|
-
* {0.1.0 release}[http://blog.smartlogicsolutions.com/2008/11/19/timecop-freeze-time-in-ruby-for-better-testing/]
|
136
|
+
Be careful mixing Ruby `Date.today` with Rails `Date.tomorrow` / `Date.yesterday` as things might break.
|
122
137
|
|
123
138
|
## Contribute
|
124
139
|
|
125
140
|
timecop is maintained by [travisjeffery](http://github.com/travisjeffery), and
|
126
|
-
was created by [jtrupiano](https://github.com/jtrupiano).
|
141
|
+
was created by [jtrupiano](https://github.com/jtrupiano).
|
127
142
|
|
128
143
|
Here's the most direct way to get your work merged into the project.
|
129
144
|
|
data/Rakefile
CHANGED
@@ -3,8 +3,6 @@ require 'bundler/gem_tasks'
|
|
3
3
|
require 'rake/testtask'
|
4
4
|
require 'rdoc/task'
|
5
5
|
|
6
|
-
$LOAD_PATH.unshift("lib")
|
7
|
-
|
8
6
|
Rake::RDocTask.new do |rdoc|
|
9
7
|
if File.exist?('VERSION')
|
10
8
|
version = File.read('VERSION')
|
@@ -20,8 +18,16 @@ Rake::RDocTask.new do |rdoc|
|
|
20
18
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
19
|
end
|
22
20
|
|
23
|
-
task :test do
|
24
|
-
|
21
|
+
task :test do
|
22
|
+
failed = Dir["test/*_test.rb"].map do |test|
|
23
|
+
command = "ruby #{test}"
|
24
|
+
puts
|
25
|
+
puts command
|
26
|
+
command unless system(command)
|
27
|
+
end.compact
|
28
|
+
if failed.any?
|
29
|
+
abort "#{failed.count} Tests failed\n#{failed.join("\n")}"
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
33
|
desc 'Default: run tests'
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'date'
|
1
3
|
|
2
4
|
class Time #:nodoc:
|
3
5
|
class << self
|
@@ -5,77 +7,148 @@ class Time #:nodoc:
|
|
5
7
|
mocked_time_stack_item = Timecop.top_stack_item
|
6
8
|
mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.time(self)
|
7
9
|
end
|
8
|
-
|
10
|
+
|
9
11
|
alias_method :now_without_mock_time, :now
|
10
12
|
|
11
13
|
def now_with_mock_time
|
12
14
|
mock_time || now_without_mock_time
|
13
15
|
end
|
14
|
-
|
16
|
+
|
15
17
|
alias_method :now, :now_with_mock_time
|
16
18
|
|
17
19
|
alias_method :new_without_mock_time, :new
|
18
20
|
|
19
21
|
def new_with_mock_time(*args)
|
20
|
-
|
21
|
-
raise ArgumentError.new if args.size <= 0
|
22
|
-
new_without_mock_time(*args)
|
23
|
-
rescue ArgumentError
|
24
|
-
now
|
25
|
-
end
|
22
|
+
args.size <= 0 ? now : new_without_mock_time(*args)
|
26
23
|
end
|
27
24
|
|
25
|
+
ruby2_keywords :new_with_mock_time if Module.private_method_defined?(:ruby2_keywords)
|
26
|
+
|
28
27
|
alias_method :new, :new_with_mock_time
|
29
28
|
end
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
class
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
29
|
+
end
|
30
|
+
|
31
|
+
class Date #:nodoc:
|
32
|
+
class << self
|
33
|
+
def mock_date
|
34
|
+
mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.date(self)
|
35
|
+
end
|
36
|
+
|
37
|
+
alias_method :today_without_mock_date, :today
|
38
|
+
|
39
|
+
def today_with_mock_date
|
40
|
+
mock_date || today_without_mock_date
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :today, :today_with_mock_date
|
44
|
+
|
45
|
+
alias_method :strptime_without_mock_date, :strptime
|
46
|
+
|
47
|
+
def strptime_with_mock_date(str = '-4712-01-01', fmt = '%F', start = Date::ITALY)
|
48
|
+
#If date is not valid the following line raises
|
49
|
+
Date.strptime_without_mock_date(str, fmt, start)
|
50
|
+
|
51
|
+
d = Date._strptime(str, fmt)
|
52
|
+
now = Time.now.to_date
|
53
|
+
year = d[:year] || now.year
|
54
|
+
mon = d[:mon] || now.mon
|
55
|
+
if d.keys == [:year]
|
56
|
+
Date.new(year, 1, 1, start)
|
57
|
+
elsif d[:mday]
|
58
|
+
Date.new(year, mon, d[:mday], start)
|
59
|
+
elsif d[:wday]
|
60
|
+
Date.new(year, mon, now.mday, start) + (d[:wday] - now.wday)
|
61
|
+
elsif d[:yday]
|
62
|
+
Date.new(year, 1, 1, start).next_day(d[:yday] - 1)
|
63
|
+
elsif d[:cwyear] && d[:cweek]
|
64
|
+
if d[:cwday]
|
65
|
+
Date.commercial(d[:cwyear], d[:cweek], d[:cwday], start)
|
66
|
+
else
|
67
|
+
Date.commercial(d[:cwyear], d[:cweek], 1, start)
|
68
|
+
end
|
69
|
+
elsif d[:seconds]
|
70
|
+
Time.at(d[:seconds]).to_date
|
71
|
+
else
|
72
|
+
Date.new(year, mon, 1, start)
|
38
73
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
74
|
+
end
|
75
|
+
|
76
|
+
alias_method :strptime, :strptime_with_mock_date
|
77
|
+
|
78
|
+
def parse_with_mock_date(*args)
|
79
|
+
parsed_date = parse_without_mock_date(*args)
|
80
|
+
return parsed_date unless mocked_time_stack_item
|
81
|
+
date_hash = Date._parse(*args)
|
82
|
+
|
83
|
+
case
|
84
|
+
when date_hash[:year] && date_hash[:mon]
|
85
|
+
parsed_date
|
86
|
+
when date_hash[:mon] && date_hash[:mday]
|
87
|
+
Date.new(mocked_time_stack_item.year, date_hash[:mon], date_hash[:mday])
|
88
|
+
when date_hash[:mday]
|
89
|
+
Date.new(mocked_time_stack_item.year, mocked_time_stack_item.month, date_hash[:mday])
|
90
|
+
when date_hash[:wday]
|
91
|
+
closest_wday(date_hash[:wday])
|
92
|
+
else
|
93
|
+
parsed_date + mocked_time_stack_item.travel_offset_days
|
44
94
|
end
|
45
|
-
|
46
|
-
|
95
|
+
end
|
96
|
+
|
97
|
+
alias_method :parse_without_mock_date, :parse
|
98
|
+
alias_method :parse, :parse_with_mock_date
|
99
|
+
|
100
|
+
def mocked_time_stack_item
|
101
|
+
Timecop.top_stack_item
|
102
|
+
end
|
103
|
+
|
104
|
+
def closest_wday(wday)
|
105
|
+
today = Date.today
|
106
|
+
result = today - today.wday
|
107
|
+
result += 1 until wday == result.wday
|
108
|
+
result
|
47
109
|
end
|
48
110
|
end
|
49
111
|
end
|
50
112
|
|
51
|
-
|
52
|
-
class
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime(self)
|
57
|
-
end
|
58
|
-
|
59
|
-
def now_without_mock_time
|
60
|
-
Time.now_without_mock_time.to_datetime
|
61
|
-
end
|
62
|
-
|
63
|
-
def now_with_mock_time
|
64
|
-
mock_time || now_without_mock_time
|
65
|
-
end
|
113
|
+
class DateTime #:nodoc:
|
114
|
+
class << self
|
115
|
+
def mock_time
|
116
|
+
mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.datetime(self)
|
117
|
+
end
|
66
118
|
|
67
|
-
|
119
|
+
def now_with_mock_time
|
120
|
+
mock_time || now_without_mock_time
|
68
121
|
end
|
69
|
-
end
|
70
122
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
123
|
+
alias_method :now_without_mock_time, :now
|
124
|
+
|
125
|
+
alias_method :now, :now_with_mock_time
|
126
|
+
|
127
|
+
def parse_with_mock_date(*args)
|
128
|
+
date_hash = Date._parse(*args)
|
129
|
+
parsed_date = parse_without_mock_date(*args)
|
130
|
+
return parsed_date unless mocked_time_stack_item
|
131
|
+
date_hash = DateTime._parse(*args)
|
132
|
+
|
133
|
+
case
|
134
|
+
when date_hash[:year] && date_hash[:mon]
|
135
|
+
parsed_date
|
136
|
+
when date_hash[:mon] && date_hash[:mday]
|
137
|
+
DateTime.new(mocked_time_stack_item.year, date_hash[:mon], date_hash[:mday])
|
138
|
+
when date_hash[:mday]
|
139
|
+
DateTime.new(mocked_time_stack_item.year, mocked_time_stack_item.month, date_hash[:mday])
|
140
|
+
when date_hash[:wday]
|
141
|
+
Date.closest_wday(date_hash[:wday]).to_datetime
|
142
|
+
else
|
143
|
+
parsed_date + mocked_time_stack_item.travel_offset_days
|
78
144
|
end
|
79
145
|
end
|
146
|
+
|
147
|
+
alias_method :parse_without_mock_date, :parse
|
148
|
+
alias_method :parse, :parse_with_mock_date
|
149
|
+
|
150
|
+
def mocked_time_stack_item
|
151
|
+
Timecop.top_stack_item
|
152
|
+
end
|
80
153
|
end
|
81
154
|
end
|
@@ -1,158 +1,140 @@
|
|
1
1
|
class Timecop
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def year
|
18
|
-
time.year
|
19
|
-
end
|
2
|
+
# A data class for carrying around "time movement" objects. Makes it easy to keep track of the time
|
3
|
+
# movements on a simple stack.
|
4
|
+
class TimeStackItem #:nodoc:
|
5
|
+
attr_reader :mock_type
|
6
|
+
|
7
|
+
def initialize(mock_type, *args)
|
8
|
+
raise "Unknown mock_type #{mock_type}" unless [:freeze, :travel, :scale].include?(mock_type)
|
9
|
+
@travel_offset = @scaling_factor = nil
|
10
|
+
@scaling_factor = args.shift if mock_type == :scale
|
11
|
+
@mock_type = mock_type
|
12
|
+
@time = parse_time(*args)
|
13
|
+
@time_was = Time.now_without_mock_time
|
14
|
+
@travel_offset = compute_travel_offset
|
15
|
+
end
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
def year
|
18
|
+
time.year
|
19
|
+
end
|
24
20
|
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
def month
|
22
|
+
time.month
|
23
|
+
end
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
def day
|
26
|
+
time.day
|
27
|
+
end
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
def hour
|
30
|
+
time.hour
|
31
|
+
end
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
def min
|
34
|
+
time.min
|
35
|
+
end
|
40
36
|
|
41
|
-
|
42
|
-
|
43
|
-
|
37
|
+
def sec
|
38
|
+
time.sec
|
39
|
+
end
|
44
40
|
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
def utc_offset
|
42
|
+
time.utc_offset
|
43
|
+
end
|
48
44
|
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
def travel_offset
|
46
|
+
@travel_offset unless mock_type == :freeze
|
47
|
+
end
|
52
48
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
calculated_time = klass.at(@time.to_f)
|
57
|
-
time = times_are_equal_within_epsilon(actual_time, calculated_time, 1) ? actual_time : calculated_time
|
58
|
-
rescue
|
59
|
-
time = klass.at(@time.to_f)
|
60
|
-
end
|
49
|
+
def travel_offset_days
|
50
|
+
(@travel_offset / 60 / 60 / 24).round
|
51
|
+
end
|
61
52
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
klass.at(Time.now_without_mock_time + travel_offset)
|
66
|
-
else
|
67
|
-
klass.at(scaled_time)
|
68
|
-
end
|
69
|
-
end
|
53
|
+
def scaling_factor
|
54
|
+
@scaling_factor
|
55
|
+
end
|
70
56
|
|
71
|
-
|
72
|
-
|
57
|
+
def time(time_klass = Time) #:nodoc:
|
58
|
+
if @time.respond_to?(:in_time_zone)
|
59
|
+
time = time_klass.at(@time.dup.localtime)
|
60
|
+
else
|
61
|
+
time = time_klass.at(@time)
|
73
62
|
end
|
74
63
|
|
75
|
-
|
76
|
-
|
64
|
+
if travel_offset.nil?
|
65
|
+
time
|
66
|
+
elsif scaling_factor.nil?
|
67
|
+
time_klass.at(Time.now_without_mock_time + travel_offset)
|
68
|
+
else
|
69
|
+
time_klass.at(scaled_time)
|
77
70
|
end
|
71
|
+
end
|
78
72
|
|
79
|
-
|
80
|
-
|
73
|
+
def scaled_time
|
74
|
+
(@time + (Time.now_without_mock_time - @time_was) * scaling_factor).to_f
|
75
|
+
end
|
81
76
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
else
|
86
|
-
our_offset = utc_offset + dst_adjustment
|
87
|
-
datetime_klass.new(year, month, day, hour, min, sec, utc_offset_to_rational(our_offset))
|
88
|
-
end
|
89
|
-
end
|
77
|
+
def date(date_klass = Date)
|
78
|
+
date_klass.jd(time.__send__(:to_date).jd)
|
79
|
+
end
|
90
80
|
|
91
|
-
|
92
|
-
|
81
|
+
def datetime(datetime_klass = DateTime)
|
82
|
+
if Float.method_defined?(:to_r)
|
83
|
+
fractions_of_a_second = time.to_f % 1
|
84
|
+
datetime_klass.new(year, month, day, hour, min, (fractions_of_a_second + sec), utc_offset_to_rational(utc_offset))
|
85
|
+
else
|
86
|
+
datetime_klass.new(year, month, day, hour, min, sec, utc_offset_to_rational(utc_offset))
|
93
87
|
end
|
88
|
+
end
|
94
89
|
|
95
|
-
|
90
|
+
private
|
96
91
|
|
97
|
-
|
98
|
-
|
99
|
-
|
92
|
+
def rational_to_utc_offset(rational)
|
93
|
+
((24.0 / rational.denominator) * rational.numerator) * (60 * 60)
|
94
|
+
end
|
100
95
|
|
101
|
-
|
102
|
-
|
103
|
-
|
96
|
+
def utc_offset_to_rational(utc_offset)
|
97
|
+
Rational(utc_offset, 24 * 60 * 60)
|
98
|
+
end
|
104
99
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
Time.now + arg
|
121
|
-
elsif arg.nil?
|
122
|
-
Time.now
|
100
|
+
def parse_time(*args)
|
101
|
+
arg = args.shift
|
102
|
+
if arg.is_a?(Time)
|
103
|
+
arg
|
104
|
+
elsif Object.const_defined?(:DateTime) && arg.is_a?(DateTime)
|
105
|
+
time_klass.at(arg.to_time.to_f).getlocal
|
106
|
+
elsif Object.const_defined?(:Date) && arg.is_a?(Date)
|
107
|
+
time_klass.local(arg.year, arg.month, arg.day, 0, 0, 0)
|
108
|
+
elsif args.empty? && (arg.kind_of?(Integer) || arg.kind_of?(Float))
|
109
|
+
time_klass.now + arg
|
110
|
+
elsif arg.nil?
|
111
|
+
time_klass.now
|
112
|
+
else
|
113
|
+
if arg.is_a?(String) && Time.respond_to?(:parse)
|
114
|
+
time_klass.parse(arg)
|
123
115
|
else
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
minute = args.shift || 0
|
133
|
-
second = args.shift || 0
|
134
|
-
time_klass.local(year, month, day, hour, minute, second)
|
135
|
-
end
|
116
|
+
# we'll just assume it's a list of y/m/d/h/m/s
|
117
|
+
year = arg || 2000
|
118
|
+
month = args.shift || 1
|
119
|
+
day = args.shift || 1
|
120
|
+
hour = args.shift || 0
|
121
|
+
minute = args.shift || 0
|
122
|
+
second = args.shift || 0
|
123
|
+
time_klass.local(year, month, day, hour, minute, second)
|
136
124
|
end
|
137
125
|
end
|
126
|
+
end
|
138
127
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
return 60 * 60
|
143
|
-
end
|
144
|
-
|
145
|
-
def compute_travel_offset
|
146
|
-
return nil if mock_type == :freeze
|
147
|
-
time - Time.now_without_mock_time
|
148
|
-
end
|
128
|
+
def compute_travel_offset
|
129
|
+
time - Time.now_without_mock_time
|
130
|
+
end
|
149
131
|
|
150
|
-
|
151
|
-
|
152
|
-
|
132
|
+
def times_are_equal_within_epsilon t1, t2, epsilon_in_seconds
|
133
|
+
(t1 - t2).abs < epsilon_in_seconds
|
134
|
+
end
|
153
135
|
|
154
|
-
|
155
|
-
|
156
|
-
end
|
136
|
+
def time_klass
|
137
|
+
Time.respond_to?(:zone) && Time.zone ? Time.zone : Time
|
157
138
|
end
|
158
139
|
end
|
140
|
+
end
|