timecop 0.9.9 → 0.9.11
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 -0
- data/lib/timecop/time_extensions.rb +60 -50
- data/lib/timecop/time_stack_item.rb +14 -16
- data/lib/timecop/timecop.rb +8 -0
- data/lib/timecop/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '079905b60d7144434c07560dadc7a1dbd36d19ad27f25ecaf52e0143e0656d23'
|
|
4
|
+
data.tar.gz: f34eb8593ccdd28571a4ccbdd710f518e628da6113eeb0f904e2f04d91dc5bf1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bd112c3657079e9c927d266725ba6d231a23658da5f385f1dca760011eff2021a30a1607cc187b26737b6d20244a0e9d54130a5a4c46b93e04c0ddebd3ba4fad
|
|
7
|
+
data.tar.gz: fa6dc270173399ff8c112624913703f612ea0d25720f13b01be67ee41781b07bd6661a502b0db1e1fdbc34fc91b4acd2966526f2ee1f1acd7463d8db26f40b8e
|
data/README.markdown
CHANGED
|
@@ -129,6 +129,15 @@ Timecop.freeze
|
|
|
129
129
|
# => Timecop::SafeModeException: Safe mode is enabled, only calls passing a block are allowed.
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
### Configuring Mocking Process.clock_gettime
|
|
133
|
+
|
|
134
|
+
By default Timecop does not mock Process.clock_gettime. You must enable it like this:
|
|
135
|
+
|
|
136
|
+
``` ruby
|
|
137
|
+
# turn on
|
|
138
|
+
Timecop.mock_process_clock = true
|
|
139
|
+
```
|
|
140
|
+
|
|
132
141
|
### Rails v Ruby Date/Time libraries
|
|
133
142
|
|
|
134
143
|
Sometimes [Rails Date/Time methods don't play nicely with Ruby Date/Time methods.](https://rails.lighthouseapp.com/projects/8994/tickets/6410-dateyesterday-datetoday)
|
|
@@ -18,12 +18,16 @@ class Time #:nodoc:
|
|
|
18
18
|
|
|
19
19
|
alias_method :new_without_mock_time, :new
|
|
20
20
|
|
|
21
|
-
def new_with_mock_time(*args)
|
|
22
|
-
args.
|
|
21
|
+
def new_with_mock_time(*args, **kwargs)
|
|
22
|
+
if args.empty? && kwargs.empty?
|
|
23
|
+
now
|
|
24
|
+
elsif kwargs.any?
|
|
25
|
+
new_without_mock_time(*args, **kwargs)
|
|
26
|
+
else
|
|
27
|
+
new_without_mock_time(*args)
|
|
28
|
+
end
|
|
23
29
|
end
|
|
24
30
|
|
|
25
|
-
ruby2_keywords :new_with_mock_time if Module.private_method_defined?(:ruby2_keywords)
|
|
26
|
-
|
|
27
31
|
alias_method :new, :new_with_mock_time
|
|
28
32
|
end
|
|
29
33
|
end
|
|
@@ -50,7 +54,12 @@ class Date #:nodoc:
|
|
|
50
54
|
|
|
51
55
|
d = Date._strptime(str, fmt)
|
|
52
56
|
now = Time.now.to_date
|
|
53
|
-
|
|
57
|
+
|
|
58
|
+
# If "current" time falls near a year boundary, with a year-ambiguous str, we need to explicitly handle it
|
|
59
|
+
cwday = d[:cwday] && (now + (d[:cwday] - now.wday))
|
|
60
|
+
wday = d[:wday] && (now + (d[:wday] - now.wday))
|
|
61
|
+
|
|
62
|
+
year = d[:year] || d[:cwyear] || (cwday || wday || now).year
|
|
54
63
|
mon = d[:mon] || now.mon
|
|
55
64
|
if d.keys == [:year]
|
|
56
65
|
Date.new(year, 1, 1, start)
|
|
@@ -59,7 +68,8 @@ class Date #:nodoc:
|
|
|
59
68
|
elsif d[:yday]
|
|
60
69
|
Date.new(year, 1, 1, start).next_day(d[:yday] - 1)
|
|
61
70
|
elsif d[:cwyear] || d[:cweek] || d[:wnum0] || d[:wnum1] || d[:wday] || d[:cwday]
|
|
62
|
-
week
|
|
71
|
+
# When only a day (wday/cwday) is present, derive the week from the resolved date; otherwise fall back to now's week
|
|
72
|
+
week = d[:cweek] || d[:wnum1] || d[:wnum0] || (cwday || wday || now).strftime('%W').to_i
|
|
63
73
|
if d[:wnum0] #Week of year where week starts on sunday
|
|
64
74
|
if d[:cwday] #monday based day of week
|
|
65
75
|
Date.strptime_without_mock_date("#{year} #{week} #{d[:cwday]}", '%Y %U %u', start)
|
|
@@ -154,6 +164,8 @@ class DateTime #:nodoc:
|
|
|
154
164
|
Date.closest_wday(date_hash[:wday]).to_datetime
|
|
155
165
|
when date_hash[:hour] && date_hash[:min] && date_hash[:sec]
|
|
156
166
|
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])
|
|
167
|
+
when date_hash[:hour] && date_hash[:min]
|
|
168
|
+
DateTime.new(mocked_time_stack_item.year, mocked_time_stack_item.month, mocked_time_stack_item.day, date_hash[:hour], date_hash[:min], 0)
|
|
157
169
|
else
|
|
158
170
|
parsed_date + mocked_time_stack_item.travel_offset_days
|
|
159
171
|
end
|
|
@@ -168,58 +180,56 @@ class DateTime #:nodoc:
|
|
|
168
180
|
end
|
|
169
181
|
end
|
|
170
182
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
|
183
|
+
module Process #:nodoc:
|
|
184
|
+
class << self
|
|
185
|
+
alias_method :clock_gettime_without_mock, :clock_gettime
|
|
186
|
+
|
|
187
|
+
def clock_gettime_mock_time(clock_id, unit = :float_second)
|
|
188
|
+
mock_time = case clock_id
|
|
189
|
+
when Process::CLOCK_MONOTONIC
|
|
190
|
+
mock_time_monotonic
|
|
191
|
+
when Process::CLOCK_REALTIME
|
|
192
|
+
mock_time_realtime
|
|
201
193
|
end
|
|
202
194
|
|
|
203
|
-
|
|
204
|
-
|
|
195
|
+
return clock_gettime_without_mock(clock_id, unit) unless Timecop.mock_process_clock? && mock_time
|
|
196
|
+
|
|
197
|
+
divisor = case unit
|
|
198
|
+
when :float_second
|
|
199
|
+
1_000_000_000.0
|
|
200
|
+
when :second
|
|
201
|
+
1_000_000_000
|
|
202
|
+
when :float_millisecond
|
|
203
|
+
1_000_000.0
|
|
204
|
+
when :millisecond
|
|
205
|
+
1_000_000
|
|
206
|
+
when :float_microsecond
|
|
207
|
+
1000.0
|
|
208
|
+
when :microsecond
|
|
209
|
+
1000
|
|
210
|
+
when :nanosecond
|
|
211
|
+
1
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
(mock_time / divisor)
|
|
215
|
+
end
|
|
205
216
|
|
|
206
|
-
|
|
217
|
+
alias_method :clock_gettime, :clock_gettime_mock_time
|
|
207
218
|
|
|
208
|
-
|
|
219
|
+
private
|
|
209
220
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
221
|
+
def mock_time_monotonic
|
|
222
|
+
mocked_time_stack_item = Timecop.top_stack_item
|
|
223
|
+
mocked_time_stack_item.nil? ? nil : mocked_time_stack_item.monotonic
|
|
224
|
+
end
|
|
214
225
|
|
|
215
|
-
|
|
216
|
-
|
|
226
|
+
def mock_time_realtime
|
|
227
|
+
mocked_time_stack_item = Timecop.top_stack_item
|
|
217
228
|
|
|
218
|
-
|
|
229
|
+
return nil if mocked_time_stack_item.nil?
|
|
219
230
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
end
|
|
231
|
+
t = mocked_time_stack_item.time
|
|
232
|
+
t.to_i * 1_000_000_000 + t.nsec
|
|
223
233
|
end
|
|
224
234
|
end
|
|
225
235
|
end
|
|
@@ -9,7 +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)
|
|
12
|
+
@monotonic = parse_monotonic_time(*args)
|
|
13
13
|
@time = parse_time(*args)
|
|
14
14
|
@time_was = Time.now_without_mock_time
|
|
15
15
|
@travel_offset = compute_travel_offset
|
|
@@ -55,24 +55,22 @@ class Timecop
|
|
|
55
55
|
@scaling_factor
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
(@monotonic + (current_monotonic - @monotonic) * scaling_factor).to_i
|
|
66
|
-
end
|
|
58
|
+
def monotonic
|
|
59
|
+
if travel_offset.nil?
|
|
60
|
+
@monotonic
|
|
61
|
+
elsif scaling_factor.nil?
|
|
62
|
+
current_monotonic + travel_offset * (10 ** 9)
|
|
63
|
+
else
|
|
64
|
+
(@monotonic + (current_monotonic - @monotonic) * scaling_factor).to_i
|
|
67
65
|
end
|
|
66
|
+
end
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
def current_monotonic
|
|
69
|
+
Process.clock_gettime_without_mock(Process::CLOCK_MONOTONIC, :nanosecond)
|
|
70
|
+
end
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
end
|
|
72
|
+
def current_monotonic_with_mock
|
|
73
|
+
Process.clock_gettime_mock_time(Process::CLOCK_MONOTONIC, :nanosecond)
|
|
76
74
|
end
|
|
77
75
|
|
|
78
76
|
def time(time_klass = Time) #:nodoc:
|
data/lib/timecop/timecop.rb
CHANGED
|
@@ -142,6 +142,14 @@ class Timecop
|
|
|
142
142
|
!instance.stack.empty? && instance.stack.last.mock_type == :scale
|
|
143
143
|
end
|
|
144
144
|
|
|
145
|
+
def mock_process_clock=(mock)
|
|
146
|
+
@mock_process_clock = mock
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def mock_process_clock?
|
|
150
|
+
@mock_process_clock ||= false
|
|
151
|
+
end
|
|
152
|
+
|
|
145
153
|
private
|
|
146
154
|
def send_travel(mock_type, *args, &block)
|
|
147
155
|
val = instance.travel(mock_type, *args, &block)
|
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.11
|
|
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: 2026-04-12 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
|
|
@@ -42,7 +42,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
42
42
|
requirements:
|
|
43
43
|
- - ">="
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: 1.
|
|
45
|
+
version: 2.1.0
|
|
46
46
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
47
|
requirements:
|
|
48
48
|
- - ">="
|