timecop 0.9.6 → 0.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.markdown +9 -9
- data/lib/timecop/time_extensions.rb +80 -9
- data/lib/timecop/time_stack_item.rb +31 -0
- data/lib/timecop/timecop.rb +18 -2
- data/lib/timecop/version.rb +1 -1
- metadata +4 -14
- data/test/test_helper.rb +0 -59
- data/test/time_stack_item_test.rb +0 -299
- data/test/timecop_test.rb +0 -622
- data/test/timecop_without_date_but_with_time_test.rb +0 -8
- data/test/timecop_without_date_test.rb +0 -118
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ffc3899071434ff0ae8eb0a9e4a6ea4c2d8794547113c272bdc24a384d2eb45
|
4
|
+
data.tar.gz: e9333e4c2cf362558c432d7b954a724ff588e66c4dcce8d3af4a327dd6dcb894
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 692759ecf208cccb83f72d2cd2a3632d6fb6477e9ac1dbf1ca19d8c23a0b864093abdfdc1d51ee98078858dc2dd3eab50f1bd8b469cc84f0619c99bed242169f
|
7
|
+
data.tar.gz: 85fc3b65a8f415601a047d4189ff497a73f49d4d48647881a6579d82dc6f12ab9e6a088da0ca2b3c2a25693f220ce3c8f31b5f2847f6a5d4784c63ace77136ff
|
data/README.markdown
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
## DESCRIPTION
|
7
7
|
|
8
|
-
A gem providing "time travel" and "time freezing" capabilities, making it dead simple to test time-dependent code.
|
8
|
+
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`, `DateTime.now`, and `Process.clock_gettime` in a single call.
|
9
9
|
|
10
10
|
## INSTALL
|
11
11
|
|
@@ -17,13 +17,13 @@ A gem providing "time travel" and "time freezing" capabilities, making it dead s
|
|
17
17
|
- Travel back to a specific point in time, but allow time to continue moving forward from there.
|
18
18
|
- Scale time by a given scaling factor that will cause time to move at an accelerated pace.
|
19
19
|
- No dependencies, can be used with _any_ ruby project
|
20
|
-
- Timecop api allows arguments to be passed into
|
20
|
+
- Timecop api allows arguments to be passed into `#freeze` and `#travel` as one of the following:
|
21
21
|
- Time instance
|
22
22
|
- DateTime instance
|
23
23
|
- Date instance
|
24
24
|
- individual arguments (year, month, day, hour, minute, second)
|
25
|
-
- a single integer argument that is interpreted as an offset in seconds from Time.now
|
26
|
-
- Nested calls to Timecop#travel and Timecop#freeze are supported -- each block will maintain its interpretation of now.
|
25
|
+
- a single integer argument that is interpreted as an offset in seconds from `Time.now`
|
26
|
+
- Nested calls to `Timecop#travel` and `Timecop#freeze` are supported -- each block will maintain its interpretation of now.
|
27
27
|
- Works with regular Ruby projects, and Ruby on Rails projects
|
28
28
|
|
29
29
|
## USAGE
|
@@ -62,7 +62,7 @@ helpful if your whole application is time-sensitive. It allows you to build
|
|
62
62
|
your test data at a single point in time, and to move in/out of that time as
|
63
63
|
appropriate (within your tests)
|
64
64
|
|
65
|
-
in config/environments/test.rb
|
65
|
+
in `config/environments/test.rb`
|
66
66
|
|
67
67
|
```ruby
|
68
68
|
config.after_initialize do
|
@@ -74,10 +74,10 @@ end
|
|
74
74
|
|
75
75
|
### The difference between Timecop.freeze and Timecop.travel
|
76
76
|
|
77
|
-
freeze is used to statically mock the concept of now. As your program executes,
|
78
|
-
Time.now will not change unless you make subsequent calls into the Timecop API.
|
79
|
-
travel
|
80
|
-
Time.now is (recall that we support nested traveling) and the time passed in.
|
77
|
+
`freeze` is used to statically mock the concept of now. As your program executes,
|
78
|
+
`Time.now` will not change unless you make subsequent calls into the Timecop API.
|
79
|
+
`travel`, on the other hand, computes an offset between what we currently think
|
80
|
+
`Time.now` is (recall that we support nested traveling) and the time passed in.
|
81
81
|
It uses this offset to simulate the passage of time. To demonstrate, consider
|
82
82
|
the following code snippets:
|
83
83
|
|
@@ -50,21 +50,28 @@ class Date #:nodoc:
|
|
50
50
|
|
51
51
|
d = Date._strptime(str, fmt)
|
52
52
|
now = Time.now.to_date
|
53
|
-
year = d[:year] || now.year
|
53
|
+
year = d[:year] || d[:cwyear] || now.year
|
54
54
|
mon = d[:mon] || now.mon
|
55
55
|
if d.keys == [:year]
|
56
56
|
Date.new(year, 1, 1, start)
|
57
57
|
elsif d[:mday]
|
58
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
59
|
elsif d[:yday]
|
62
60
|
Date.new(year, 1, 1, start).next_day(d[:yday] - 1)
|
63
|
-
elsif d[:cwyear]
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
61
|
+
elsif d[:cwyear] || d[:cweek] || d[:wnum0] || d[:wnum1] || d[:wday] || d[:cwday]
|
62
|
+
week = d[:cweek] || d[:wnum1] || d[:wnum0] || now.strftime('%W').to_i
|
63
|
+
if d[:wnum0] #Week of year where week starts on sunday
|
64
|
+
if d[:cwday] #monday based day of week
|
65
|
+
Date.strptime_without_mock_date("#{year} #{week} #{d[:cwday]}", '%Y %U %u', start)
|
66
|
+
else
|
67
|
+
Date.strptime_without_mock_date("#{year} #{week} #{d[:wday] || 0}", '%Y %U %w', start)
|
68
|
+
end
|
69
|
+
else #Week of year where week starts on monday
|
70
|
+
if d[:wday] #sunday based day of week
|
71
|
+
Date.strptime_without_mock_date("#{year} #{week} #{d[:wday]}", '%Y %W %w', start)
|
72
|
+
else
|
73
|
+
Date.strptime_without_mock_date("#{year} #{week} #{d[:cwday] || 1}", '%Y %W %u', start)
|
74
|
+
end
|
68
75
|
end
|
69
76
|
elsif d[:seconds]
|
70
77
|
Time.at(d[:seconds]).to_date
|
@@ -125,7 +132,6 @@ class DateTime #:nodoc:
|
|
125
132
|
alias_method :now, :now_with_mock_time
|
126
133
|
|
127
134
|
def parse_with_mock_date(*args)
|
128
|
-
date_hash = Date._parse(*args)
|
129
135
|
parsed_date = parse_without_mock_date(*args)
|
130
136
|
return parsed_date unless mocked_time_stack_item
|
131
137
|
date_hash = DateTime._parse(*args)
|
@@ -137,8 +143,17 @@ class DateTime #:nodoc:
|
|
137
143
|
DateTime.new(mocked_time_stack_item.year, date_hash[:mon], date_hash[:mday])
|
138
144
|
when date_hash[:mday]
|
139
145
|
DateTime.new(mocked_time_stack_item.year, mocked_time_stack_item.month, date_hash[:mday])
|
146
|
+
when date_hash[:wday] && date_hash[:hour] && date_hash[:min]
|
147
|
+
closest_date = Date.closest_wday(date_hash[:wday]).to_datetime
|
148
|
+
|
149
|
+
DateTime.new(
|
150
|
+
closest_date.year, closest_date.month, closest_date.day,
|
151
|
+
date_hash[:hour], date_hash[:min]
|
152
|
+
)
|
140
153
|
when date_hash[:wday]
|
141
154
|
Date.closest_wday(date_hash[:wday]).to_datetime
|
155
|
+
when date_hash[:hour] && date_hash[:min] && date_hash[:sec]
|
156
|
+
DateTime.new(mocked_time_stack_item.year, mocked_time_stack_item.month, mocked_time_stack_item.day, date_hash[:hour], date_hash[:min], date_hash[:sec])
|
142
157
|
else
|
143
158
|
parsed_date + mocked_time_stack_item.travel_offset_days
|
144
159
|
end
|
@@ -152,3 +167,59 @@ class DateTime #:nodoc:
|
|
152
167
|
end
|
153
168
|
end
|
154
169
|
end
|
170
|
+
|
171
|
+
if RUBY_VERSION >= '2.1.0'
|
172
|
+
module Process #:nodoc:
|
173
|
+
class << self
|
174
|
+
alias_method :clock_gettime_without_mock, :clock_gettime
|
175
|
+
|
176
|
+
def clock_gettime_mock_time(clock_id, unit = :float_second)
|
177
|
+
mock_time = case clock_id
|
178
|
+
when Process::CLOCK_MONOTONIC
|
179
|
+
mock_time_monotonic
|
180
|
+
when Process::CLOCK_REALTIME
|
181
|
+
mock_time_realtime
|
182
|
+
end
|
183
|
+
|
184
|
+
return clock_gettime_without_mock(clock_id, unit) unless mock_time
|
185
|
+
|
186
|
+
divisor = case unit
|
187
|
+
when :float_second
|
188
|
+
1_000_000_000.0
|
189
|
+
when :second
|
190
|
+
1_000_000_000
|
191
|
+
when :float_millisecond
|
192
|
+
1_000_000.0
|
193
|
+
when :millisecond
|
194
|
+
1_000_000
|
195
|
+
when :float_microsecond
|
196
|
+
1000.0
|
197
|
+
when :microsecond
|
198
|
+
1000
|
199
|
+
when :nanosecond
|
200
|
+
1
|
201
|
+
end
|
202
|
+
|
203
|
+
(mock_time / divisor)
|
204
|
+
end
|
205
|
+
|
206
|
+
alias_method :clock_gettime, :clock_gettime_mock_time
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
def mock_time_monotonic
|
211
|
+
mocked_time_stack_item = Timecop.top_stack_item
|
212
|
+
mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.monotonic
|
213
|
+
end
|
214
|
+
|
215
|
+
def mock_time_realtime
|
216
|
+
mocked_time_stack_item = Timecop.top_stack_item
|
217
|
+
|
218
|
+
return nil if mocked_time_stack_item.nil?
|
219
|
+
|
220
|
+
t = mocked_time_stack_item.time
|
221
|
+
t.to_i * 1_000_000_000 + t.nsec
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -9,6 +9,7 @@ class Timecop
|
|
9
9
|
@travel_offset = @scaling_factor = nil
|
10
10
|
@scaling_factor = args.shift if mock_type == :scale
|
11
11
|
@mock_type = mock_type
|
12
|
+
@monotonic = parse_monotonic_time(*args) if RUBY_VERSION >= '2.1.0'
|
12
13
|
@time = parse_time(*args)
|
13
14
|
@time_was = Time.now_without_mock_time
|
14
15
|
@travel_offset = compute_travel_offset
|
@@ -54,6 +55,26 @@ class Timecop
|
|
54
55
|
@scaling_factor
|
55
56
|
end
|
56
57
|
|
58
|
+
if RUBY_VERSION >= '2.1.0'
|
59
|
+
def monotonic
|
60
|
+
if travel_offset.nil?
|
61
|
+
@monotonic
|
62
|
+
elsif scaling_factor.nil?
|
63
|
+
current_monotonic + travel_offset * (10 ** 9)
|
64
|
+
else
|
65
|
+
(@monotonic + (current_monotonic - @monotonic) * scaling_factor).to_i
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def current_monotonic
|
70
|
+
Process.clock_gettime_without_mock(Process::CLOCK_MONOTONIC, :nanosecond)
|
71
|
+
end
|
72
|
+
|
73
|
+
def current_monotonic_with_mock
|
74
|
+
Process.clock_gettime_mock_time(Process::CLOCK_MONOTONIC, :nanosecond)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
57
78
|
def time(time_klass = Time) #:nodoc:
|
58
79
|
if @time.respond_to?(:in_time_zone)
|
59
80
|
time = time_klass.at(@time.dup.localtime)
|
@@ -97,6 +118,16 @@ class Timecop
|
|
97
118
|
Rational(utc_offset, 24 * 60 * 60)
|
98
119
|
end
|
99
120
|
|
121
|
+
def parse_monotonic_time(*args)
|
122
|
+
arg = args.shift
|
123
|
+
offset_in_nanoseconds = if args.empty? && (arg.kind_of?(Integer) || arg.kind_of?(Float))
|
124
|
+
arg * 1_000_000_000
|
125
|
+
else
|
126
|
+
0
|
127
|
+
end
|
128
|
+
current_monotonic_with_mock + offset_in_nanoseconds
|
129
|
+
end
|
130
|
+
|
100
131
|
def parse_time(*args)
|
101
132
|
arg = args.shift
|
102
133
|
if arg.is_a?(Time)
|
data/lib/timecop/timecop.rb
CHANGED
@@ -38,6 +38,12 @@ class Timecop
|
|
38
38
|
# previous values after the block has finished executing. This allows us to nest multiple
|
39
39
|
# calls to Timecop.travel and have each block maintain it's concept of "now."
|
40
40
|
#
|
41
|
+
# The Process.clock_gettime call mocks both CLOCK::MONOTIC and CLOCK::REALTIME
|
42
|
+
#
|
43
|
+
# CLOCK::MONOTONIC works slightly differently than other clocks. This clock cannot move to a
|
44
|
+
# particular date/time. So the only option that changes this clock is #4 which will move the
|
45
|
+
# clock the requested offset. Otherwise the clock is frozen to the current tick.
|
46
|
+
#
|
41
47
|
# * Note: Timecop.freeze will actually freeze time. This can cause unanticipated problems if
|
42
48
|
# benchmark or other timing calls are executed, which implicitly expect Time to actually move
|
43
49
|
# forward.
|
@@ -121,9 +127,19 @@ class Timecop
|
|
121
127
|
instance.thread_safe
|
122
128
|
end
|
123
129
|
|
124
|
-
# Returns whether or not Timecop is currently frozen
|
130
|
+
# Returns whether or not Timecop is currently frozen
|
125
131
|
def frozen?
|
126
|
-
!instance.stack.empty?
|
132
|
+
!instance.stack.empty? && instance.stack.last.mock_type == :freeze
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns whether or not Timecop is currently travelled
|
136
|
+
def travelled?
|
137
|
+
!instance.stack.empty? && instance.stack.last.mock_type == :travel
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns whether or not Timecop is currently scaled
|
141
|
+
def scaled?
|
142
|
+
!instance.stack.empty? && instance.stack.last.mock_type == :scale
|
127
143
|
end
|
128
144
|
|
129
145
|
private
|
data/lib/timecop/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timecop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Travis Jeffery
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-06-01 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A gem providing "time travel" and "time freezing" capabilities, making
|
15
15
|
it dead simple to test time-dependent code. It provides a unified method to mock
|
@@ -29,11 +29,6 @@ files:
|
|
29
29
|
- lib/timecop/time_stack_item.rb
|
30
30
|
- lib/timecop/timecop.rb
|
31
31
|
- lib/timecop/version.rb
|
32
|
-
- test/test_helper.rb
|
33
|
-
- test/time_stack_item_test.rb
|
34
|
-
- test/timecop_test.rb
|
35
|
-
- test/timecop_without_date_but_with_time_test.rb
|
36
|
-
- test/timecop_without_date_test.rb
|
37
32
|
homepage: https://github.com/travisjeffery/timecop
|
38
33
|
licenses:
|
39
34
|
- MIT
|
@@ -56,13 +51,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
51
|
requirements: []
|
57
52
|
rubygems_version: 3.2.15
|
58
53
|
signing_key:
|
59
|
-
specification_version:
|
54
|
+
specification_version: 4
|
60
55
|
summary: A gem providing "time travel" and "time freezing" capabilities, making it
|
61
56
|
dead simple to test time-dependent code. It provides a unified method to mock Time.now,
|
62
57
|
Date.today, and DateTime.now in a single call.
|
63
|
-
test_files:
|
64
|
-
- test/test_helper.rb
|
65
|
-
- test/time_stack_item_test.rb
|
66
|
-
- test/timecop_test.rb
|
67
|
-
- test/timecop_without_date_test.rb
|
68
|
-
- test/timecop_without_date_but_with_time_test.rb
|
58
|
+
test_files: []
|
data/test/test_helper.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'bundler/setup'
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'minitest/rg'
|
4
|
-
require 'pry'
|
5
|
-
|
6
|
-
$VERBOSE = true # enable ruby warnings
|
7
|
-
|
8
|
-
require 'mocha/minitest'
|
9
|
-
|
10
|
-
class Minitest::Test
|
11
|
-
private
|
12
|
-
# Tests to see that two times are within the given distance,
|
13
|
-
# in seconds, from each other.
|
14
|
-
def times_effectively_equal(time1, time2, seconds_interval = 1)
|
15
|
-
(time1 - time2).abs <= seconds_interval
|
16
|
-
end
|
17
|
-
|
18
|
-
def assert_times_effectively_equal(time1, time2, seconds_interval = 1, msg = nil)
|
19
|
-
assert times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}"
|
20
|
-
end
|
21
|
-
|
22
|
-
def assert_times_effectively_not_equal(time1, time2, seconds_interval = 1, msg = nil)
|
23
|
-
assert !times_effectively_equal(time1, time2, seconds_interval), "#{msg}: time1 = #{time1.to_s}, time2 = #{time2.to_s}"
|
24
|
-
end
|
25
|
-
|
26
|
-
# Gets the local offset (supplied by ENV['TZ'] or your computer's clock)
|
27
|
-
# At the given timestamp, or Time.now if not time is given.
|
28
|
-
def local_offset(time = Time.now)
|
29
|
-
Time.at(time.to_i).to_datetime.offset
|
30
|
-
end
|
31
|
-
|
32
|
-
TIMEZONES = ["Pacific/Midway", "Europe/Paris", "UTC", "America/Chicago"]
|
33
|
-
|
34
|
-
def each_timezone
|
35
|
-
old_tz = ENV["TZ"]
|
36
|
-
|
37
|
-
begin
|
38
|
-
TIMEZONES.each do |timezone|
|
39
|
-
ENV["TZ"] = timezone
|
40
|
-
yield
|
41
|
-
end
|
42
|
-
ensure
|
43
|
-
ENV["TZ"] = old_tz
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def a_time_stack_item
|
48
|
-
Timecop::TimeStackItem.new(:freeze, 2008, 1, 1, 0, 0, 0)
|
49
|
-
end
|
50
|
-
|
51
|
-
def assert_date_times_equal(dt1, dt2)
|
52
|
-
assert_in_delta dt1.to_time.to_f, dt2.to_time.to_f, 0.01, "Failed for timezone: #{ENV['TZ']}: #{dt1.to_s} not equal to #{dt2.to_s}"
|
53
|
-
end
|
54
|
-
|
55
|
-
def jruby?
|
56
|
-
RUBY_PLATFORM == "java"
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
@@ -1,299 +0,0 @@
|
|
1
|
-
require 'date'
|
2
|
-
require_relative "test_helper"
|
3
|
-
require 'timecop'
|
4
|
-
|
5
|
-
require 'active_support/all'
|
6
|
-
|
7
|
-
class TestTimeStackItem < Minitest::Test
|
8
|
-
def teardown
|
9
|
-
Timecop.return
|
10
|
-
Time.zone = nil
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_new_with_time
|
14
|
-
t = Time.now
|
15
|
-
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
16
|
-
stack_item = Timecop::TimeStackItem.new(:freeze, t)
|
17
|
-
|
18
|
-
assert_equal y, stack_item.year
|
19
|
-
assert_equal m, stack_item.month
|
20
|
-
assert_equal d, stack_item.day
|
21
|
-
assert_equal h, stack_item.hour
|
22
|
-
assert_equal min, stack_item.min
|
23
|
-
assert_equal s, stack_item.sec
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_new_with_time_and_arguments
|
27
|
-
t = Time.new(2012, 7, 28, 20, 0)
|
28
|
-
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
29
|
-
stack_item = Timecop::TimeStackItem.new(:freeze, t)
|
30
|
-
|
31
|
-
assert_equal y, stack_item.year
|
32
|
-
assert_equal m, stack_item.month
|
33
|
-
assert_equal d, stack_item.day
|
34
|
-
assert_equal h, stack_item.hour
|
35
|
-
assert_equal min, stack_item.min
|
36
|
-
assert_equal s, stack_item.sec
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_new_with_datetime_now
|
40
|
-
t = DateTime.now
|
41
|
-
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
42
|
-
stack_item = Timecop::TimeStackItem.new(:freeze, t)
|
43
|
-
|
44
|
-
assert_equal y, stack_item.year
|
45
|
-
assert_equal m, stack_item.month
|
46
|
-
assert_equal d, stack_item.day
|
47
|
-
assert_equal h, stack_item.hour
|
48
|
-
assert_equal min, stack_item.min
|
49
|
-
assert_equal s, stack_item.sec
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_new_with_datetime_in_different_timezone
|
53
|
-
each_timezone do
|
54
|
-
t = DateTime.parse("2009-10-11 00:38:00 +0200")
|
55
|
-
stack_item = Timecop::TimeStackItem.new(:freeze, t)
|
56
|
-
|
57
|
-
assert_date_times_equal(t, stack_item.datetime)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def test_new_with_date
|
62
|
-
date = Date.today
|
63
|
-
y, m, d, h, min, s = date.year, date.month, date.day, 0, 0, 0
|
64
|
-
stack_item = Timecop::TimeStackItem.new(:freeze, date)
|
65
|
-
|
66
|
-
assert_equal y, stack_item.year
|
67
|
-
assert_equal m, stack_item.month
|
68
|
-
assert_equal d, stack_item.day
|
69
|
-
assert_equal h, stack_item.hour
|
70
|
-
assert_equal min, stack_item.min
|
71
|
-
assert_equal s, stack_item.sec
|
72
|
-
end
|
73
|
-
|
74
|
-
# Due to the nature of this test (calling Time.now once in this test and
|
75
|
-
# once in #new), this test may fail when two subsequent calls
|
76
|
-
# to Time.now return a different second.
|
77
|
-
def test_new_with_integer
|
78
|
-
t = Time.now
|
79
|
-
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
80
|
-
stack_item = Timecop::TimeStackItem.new(:freeze, 0)
|
81
|
-
|
82
|
-
assert_equal y, stack_item.year
|
83
|
-
assert_equal m, stack_item.month
|
84
|
-
assert_equal d, stack_item.day
|
85
|
-
assert_equal h, stack_item.hour
|
86
|
-
assert_equal min, stack_item.min
|
87
|
-
assert_equal s, stack_item.sec
|
88
|
-
end
|
89
|
-
|
90
|
-
def test_new_with_float
|
91
|
-
t = Time.now
|
92
|
-
y, m, d, h, min, s = t.year, t.month, t.day, t.hour, t.min, t.sec
|
93
|
-
stack_item = Timecop::TimeStackItem.new(:freeze, 0.0)
|
94
|
-
|
95
|
-
assert_equal y, stack_item.year
|
96
|
-
assert_equal m, stack_item.month
|
97
|
-
assert_equal d, stack_item.day
|
98
|
-
assert_equal h, stack_item.hour
|
99
|
-
assert_equal min, stack_item.min
|
100
|
-
assert_equal s, stack_item.sec
|
101
|
-
end
|
102
|
-
|
103
|
-
def test_new_with_individual_arguments
|
104
|
-
y, m, d, h, min, s = 2008, 10, 10, 10, 10, 10
|
105
|
-
stack_item = Timecop::TimeStackItem.new(:freeze, y, m, d, h, min, s)
|
106
|
-
|
107
|
-
assert_equal y, stack_item.year
|
108
|
-
assert_equal m, stack_item.month
|
109
|
-
assert_equal d, stack_item.day
|
110
|
-
assert_equal h, stack_item.hour
|
111
|
-
assert_equal min, stack_item.min
|
112
|
-
assert_equal s, stack_item.sec
|
113
|
-
end
|
114
|
-
|
115
|
-
def test_rational_to_utc_offset
|
116
|
-
assert_equal -14400, a_time_stack_item.send(:rational_to_utc_offset, Rational(-1, 6))
|
117
|
-
assert_equal -18000, a_time_stack_item.send(:rational_to_utc_offset, Rational(-5, 24))
|
118
|
-
assert_equal 0, a_time_stack_item.send(:rational_to_utc_offset, Rational(0, 1))
|
119
|
-
assert_equal 3600, a_time_stack_item.send(:rational_to_utc_offset, Rational(1, 24))
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_utc_offset_to_rational
|
123
|
-
assert_equal Rational(-1, 6), a_time_stack_item.send(:utc_offset_to_rational, -14400)
|
124
|
-
assert_equal Rational(-5, 24), a_time_stack_item.send(:utc_offset_to_rational, -18000)
|
125
|
-
assert_equal Rational(0, 1), a_time_stack_item.send(:utc_offset_to_rational, 0)
|
126
|
-
assert_equal Rational(1, 24), a_time_stack_item.send(:utc_offset_to_rational, 3600)
|
127
|
-
end
|
128
|
-
|
129
|
-
def test_datetime_in_presence_of_activesupport_timezone
|
130
|
-
skip('requires ActiveSupport') unless Time.respond_to? :zone
|
131
|
-
backed_up_zone, backed_up_tzvar = Time.zone, ENV['TZ']
|
132
|
-
|
133
|
-
Time.zone = ENV['TZ'] = 'America/Los_Angeles'
|
134
|
-
t = DateTime.new(2001, 2, 28, 23, 59, 59.5)
|
135
|
-
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
136
|
-
|
137
|
-
assert_date_times_equal t, tsi.datetime
|
138
|
-
ensure
|
139
|
-
Time.zone, ENV['TZ'] = backed_up_zone, backed_up_tzvar
|
140
|
-
end
|
141
|
-
|
142
|
-
# Ensure DateTimes handle changing DST properly
|
143
|
-
def test_datetime_for_dst_to_non_dst
|
144
|
-
Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500"))
|
145
|
-
t = DateTime.parse("2009-10-11 00:00:00 -0400")
|
146
|
-
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
147
|
-
|
148
|
-
assert_date_times_equal t, tsi.datetime
|
149
|
-
end
|
150
|
-
|
151
|
-
# Ensure DateTimes handle changing DST properly when changing from DateTime to Time
|
152
|
-
def test_datetime_for_dst_to_time_for_non_dst
|
153
|
-
Timecop.freeze(DateTime.parse("2009-12-1 00:38:00 -0500"))
|
154
|
-
t = DateTime.parse("2009-10-11 00:00:00 -0400")
|
155
|
-
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
156
|
-
|
157
|
-
assert_date_times_equal t.to_time, tsi.time
|
158
|
-
end
|
159
|
-
|
160
|
-
def test_datetime_for_non_dst_to_dst
|
161
|
-
Timecop.freeze(DateTime.parse("2009-10-11 00:00:00 -0400"))
|
162
|
-
t = DateTime.parse("2009-11-30 23:38:00 -0500")
|
163
|
-
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
164
|
-
return if !tsi.time.dst?
|
165
|
-
|
166
|
-
assert_date_times_equal t, tsi.datetime
|
167
|
-
assert_equal Date.new(2009, 12, 1), tsi.date
|
168
|
-
end
|
169
|
-
|
170
|
-
def test_set_travel_offset_for_travel
|
171
|
-
t_now = Time.now
|
172
|
-
t = Time.local(2009, 10, 1, 0, 0, 30)
|
173
|
-
expected_offset = t - t_now
|
174
|
-
tsi = Timecop::TimeStackItem.new(:travel, t)
|
175
|
-
|
176
|
-
assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly"
|
177
|
-
end
|
178
|
-
|
179
|
-
def test_set_travel_offset_for_freeze
|
180
|
-
Timecop.freeze(2009, 10, 1, 0, 0, 0)
|
181
|
-
t = Time.local(2009, 10, 1, 0, 0, 30)
|
182
|
-
tsi = Timecop::TimeStackItem.new(:freeze, t)
|
183
|
-
|
184
|
-
assert_nil tsi.send(:travel_offset)
|
185
|
-
end
|
186
|
-
|
187
|
-
def test_timezones
|
188
|
-
Time.zone = "Europe/Zurich"
|
189
|
-
time = Time.zone.parse("2012-12-27T12:12:12+08:00")
|
190
|
-
Timecop.freeze(time) do |frozen_time|
|
191
|
-
assert_equal time, frozen_time
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def test_timezones_with_parsed_string
|
196
|
-
Time.zone = "Europe/Zurich"
|
197
|
-
time_string = "2012-12-27 12:12"
|
198
|
-
expected_time = Time.zone.parse(time_string)
|
199
|
-
Timecop.freeze(time_string) do |frozen_time|
|
200
|
-
assert_equal expected_time, frozen_time
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def test_timezones_apply_dates
|
205
|
-
Time.zone = "Central Time (US & Canada)"
|
206
|
-
time = Time.zone.local(2013,1,3)
|
207
|
-
|
208
|
-
Timecop.freeze(time) do
|
209
|
-
assert_equal time.to_date, Time.zone.now.to_date
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def test_set_scaling_factor_for_scale
|
214
|
-
t_now = Time.now
|
215
|
-
t = Time.local(2009, 10, 1, 0, 0, 30)
|
216
|
-
expected_offset = t - t_now
|
217
|
-
tsi = Timecop::TimeStackItem.new(:scale, 4, t)
|
218
|
-
|
219
|
-
assert_times_effectively_equal expected_offset, tsi.send(:travel_offset), 1, "Offset not calculated correctly"
|
220
|
-
assert_equal tsi.send(:scaling_factor), 4, "Scaling factor not set"
|
221
|
-
end
|
222
|
-
|
223
|
-
def test_parse_only_string_with_active_support
|
224
|
-
Time.expects(:parse).never
|
225
|
-
Timecop.freeze(2011, 01, 02, hour=0, minute=0, second=0)
|
226
|
-
end
|
227
|
-
|
228
|
-
def test_parse_date
|
229
|
-
Timecop.freeze(Date.new(2012, 6, 9))
|
230
|
-
end
|
231
|
-
|
232
|
-
def test_time_zone_returns_nil
|
233
|
-
Time.zone = nil
|
234
|
-
Timecop.freeze
|
235
|
-
end
|
236
|
-
|
237
|
-
def test_nsecs_are_set
|
238
|
-
time = Time.now
|
239
|
-
Timecop.freeze time
|
240
|
-
assert_equal time, Time.now
|
241
|
-
assert_equal time.nsec, Time.now.nsec if (Time.now.respond_to?(:nsec))
|
242
|
-
end
|
243
|
-
|
244
|
-
def test_time_with_different_timezone_keeps_nsec
|
245
|
-
Time.zone = "Tokyo"
|
246
|
-
t = Time.now
|
247
|
-
Timecop.freeze(t) do
|
248
|
-
assert_equal t, Time.now
|
249
|
-
assert_equal t.nsec, Time.now.nsec if (Time.now.respond_to?(:nsec))
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
def test_time_now_always_returns_local_time
|
254
|
-
Time.zone = "Tokyo"
|
255
|
-
t = Time.utc(2000, 1, 1)
|
256
|
-
Timecop.freeze(t) do
|
257
|
-
assert_equal t.getlocal.zone, Time.now.zone
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
def test_time_zone_now_returns_time_in_that_zone
|
262
|
-
Time.zone = "Hawaii"
|
263
|
-
t = Time.utc(2000, 1, 1)
|
264
|
-
Timecop.freeze(t) do
|
265
|
-
assert_equal t, Time.zone.now
|
266
|
-
assert_equal 'HST', Time.zone.now.zone
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
def test_freezing_a_time_leaves_timezone_intact
|
271
|
-
Time.zone = "Tokyo"
|
272
|
-
t = Time.now
|
273
|
-
t_dup = t.dup
|
274
|
-
Timecop.freeze(t) {}
|
275
|
-
assert_equal t_dup.zone, t.zone
|
276
|
-
end
|
277
|
-
|
278
|
-
def test_freezing_a_time_with_zone_returns_proper_zones
|
279
|
-
Time.zone = "Hawaii"
|
280
|
-
t = ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1), ActiveSupport::TimeZone['Tokyo'])
|
281
|
-
Timecop.freeze(t) do
|
282
|
-
local_now = Time.now
|
283
|
-
assert_equal t, local_now
|
284
|
-
assert_equal t.getlocal.zone, local_now.zone
|
285
|
-
|
286
|
-
zoned_now = Time.zone.now
|
287
|
-
assert_equal t, zoned_now
|
288
|
-
assert_equal 'HST', zoned_now.zone
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
def test_datetime_timezones
|
293
|
-
dt = DateTime.new(2011,1,3,15,25,0,"-6")
|
294
|
-
Timecop.freeze(dt) do
|
295
|
-
now = DateTime.now
|
296
|
-
assert_equal dt, now, "#{dt.to_f}, #{now.to_f}"
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|