├── .gitignore
├── README.md
├── pom.xml
└── src
├── test
└── java
│ └── com
│ └── statemachinesystems
│ └── mockclock
│ └── MockClockTest.java
└── main
└── java
└── com
└── statemachinesystems
└── mockclock
└── MockClock.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | pom.xml.tag
3 | pom.xml.releaseBackup
4 | pom.xml.next
5 | dependency-reduced-pom.xml
6 | release.properties
7 | .idea/
8 | *.iml
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Java 8's `Clock` class is a big step in the right direction for testability, but it's still a pain. You can
2 | test using `Clock.fixed()` but that's immutable so you can't test how your code responds to the passage of time.
3 | You can use a mocking library to stub the `instant()` and `getZone()` methods, but that's still awkward and indirect.
4 |
5 | This library provides a mutable `MockClock` class that can be constructed as of a given date and time, then adjusted as
6 | needed. Here's an example of how to use it:
7 |
8 |
9 | import com.statemachinesystems.mockclock.MockClock;
10 | import java.time.ZoneId;
11 |
12 | MockClock clock = MockClock.at(2015, 12, 10, 11, 16, ZoneId.of("UTC"));
13 | ClassUnderTest testSubject = new ClassUnderTest(clock);
14 |
15 | assertThat(testSubject.someMethod(), is(expectedValueAtStartTime));
16 |
17 | clock.advanceBySeconds(30);
18 |
19 | assertThat(testSubject.someMethod(), is(expectedValueAfter30Seconds));
20 |
21 | This library is in the Maven Central repo, so just add the following chunk to your pom.xml (or the equivalent for Gradle/SBT/whatever):
22 |
23 |
24 | com.statemachinesystems
25 | mock-clock
26 | 1.0
27 |
28 |
29 |
30 | © 2015 State Machine Systems Ltd. [Apache Licence, Version 2.0]( http://www.apache.org/licenses/LICENSE-2.0)
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | com.statemachinesystems
6 | mock-clock
7 | 1.1-SNAPSHOT
8 | jar
9 |
10 | mock-clock
11 | A mock Clock implementation for Java.
12 | https://github.com/state-machine-systems/mock-clock
13 |
14 |
15 |
16 | Apache License, Version 2.0
17 | http://www.apache.org/licenses/LICENSE-2.0.txt
18 | repo
19 |
20 |
21 |
22 |
23 | scm:git:git@github.com:state-machine-systems/mock-clock.git
24 | scm:git:git@github.com:state-machine-systems/mock-clock.git
25 | git@github.com:state-machine-systems/mock-clock.git
26 | HEAD
27 |
28 |
29 |
30 |
31 | johnwright
32 | John Wright
33 | john@statemachinesystems.co.uk
34 | State Machine Systems
35 | http://www.statemachinesystems.co.uk
36 |
37 |
38 |
39 |
40 | 0.7.1.201405082137
41 | 1.8
42 | 1.8
43 | 4.12
44 | 3.1
45 | 2.8.2
46 | 1.5
47 | 2.10.1
48 | 2.5.1
49 | 2.4
50 | 2.17
51 | UTF-8
52 |
53 |
54 |
55 |
56 | junit
57 | junit
58 | ${junit.version}
59 | test
60 |
61 |
62 |
63 |
64 |
65 |
66 | org.apache.maven.plugins
67 | maven-compiler-plugin
68 | ${maven.compiler.plugin.version}
69 |
70 | ${java.source.version}
71 | ${java.target.version}
72 |
73 |
74 |
75 | org.apache.maven.plugins
76 | maven-surefire-plugin
77 | ${maven.surefire.plugin.version}
78 |
79 |
80 | default-test
81 | test
82 |
83 | test
84 |
85 |
86 | ${jacocoAgentConfigArgs}
87 |
88 | **/integration/*.*
89 |
90 |
91 |
92 |
93 |
94 |
95 | org.jacoco
96 | jacoco-maven-plugin
97 | ${jacoco.version}
98 |
99 |
100 | jacoco-init
101 | process-test-classes
102 |
103 | prepare-agent
104 |
105 |
106 | jacocoAgentConfigArgs
107 |
108 |
109 |
110 | jacoco-report
111 | verify
112 |
113 | report
114 |
115 |
116 |
117 |
118 |
119 | org.apache.maven.plugins
120 | maven-release-plugin
121 | ${maven.release.plugin.version}
122 |
123 |
124 | org.apache.maven.plugins
125 | maven-source-plugin
126 | ${maven.source.plugin.version}
127 |
128 |
129 | attach-sources
130 |
131 | jar
132 |
133 |
134 |
135 |
136 |
137 | org.apache.maven.plugins
138 | maven-javadoc-plugin
139 | ${maven.javadoc.plugin.version}
140 |
141 |
142 | attach-javadocs
143 |
144 | jar
145 |
146 |
147 |
148 |
149 |
150 | org.apache.maven.plugins
151 | maven-deploy-plugin
152 | ${maven.deploy.plugin.version}
153 |
154 |
155 |
156 |
157 |
158 |
159 | release-sign-artifacts
160 |
161 |
162 | performRelease
163 | true
164 |
165 |
166 |
167 |
168 |
169 | org.apache.maven.plugins
170 | maven-gpg-plugin
171 | ${maven.gpg.plugin.version}
172 |
173 | true
174 |
175 |
176 |
177 | sign-artifacts
178 | verify
179 |
180 | sign
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 | sonatype-nexus-snapshots
193 | Sonatype Nexus snapshot repository
194 | https://oss.sonatype.org/content/repositories/snapshots
195 |
196 |
197 | sonatype-nexus-staging
198 | Sonatype Nexus release repository
199 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
200 |
201 |
202 |
--------------------------------------------------------------------------------
/src/test/java/com/statemachinesystems/mockclock/MockClockTest.java:
--------------------------------------------------------------------------------
1 | package com.statemachinesystems.mockclock;
2 |
3 | import java.time.Clock;
4 | import java.time.Duration;
5 | import java.time.Instant;
6 | import java.time.LocalDate;
7 | import java.time.LocalDateTime;
8 | import java.time.LocalTime;
9 | import java.time.Month;
10 | import java.time.ZoneId;
11 | import java.time.ZonedDateTime;
12 | import org.junit.Test;
13 |
14 | import static java.time.Month.*;
15 | import static org.hamcrest.CoreMatchers.is;
16 | import static org.junit.Assert.assertThat;
17 |
18 | public class MockClockTest {
19 |
20 | private static final ZoneId UTC = ZoneId.of("UTC");
21 |
22 | private static final int YEAR = 2015;
23 | private static final Month MONTH = DECEMBER;
24 | private static final int DAY_OF_MONTH = 9;
25 | private static final int HOUR = 12;
26 | private static final int MINUTE = 25;
27 | private static final int SECOND = 38;
28 | private static final int NANO_OF_SECOND = 111;
29 | private static final LocalDate LOCAL_DATE = LocalDate.of(YEAR, MONTH, DAY_OF_MONTH);
30 | private static final LocalTime LOCAL_TIME = LocalTime.of(HOUR, MINUTE, SECOND, NANO_OF_SECOND);
31 | private static final LocalDateTime LOCAL_DATE_TIME = LocalDateTime.of(LOCAL_DATE, LOCAL_TIME);
32 | private static final Instant DATE_TIME_INSTANT = LOCAL_DATE_TIME.atZone(UTC).toInstant();
33 | private static final Instant DATE_ONLY_INSTANT = LOCAL_DATE.atStartOfDay(UTC).toInstant();
34 |
35 | @Test
36 | public void constructUsingSystemClock() {
37 | Clock systemClock = Clock.system(UTC);
38 | Instant now = systemClock.instant();
39 |
40 | MockClock mockClock = MockClock.now(UTC).setNano(0);
41 |
42 | Instant roundedInstant = ZonedDateTime.ofInstant(now, UTC).withNano(0).toInstant();
43 | assertClockInstant(mockClock, roundedInstant);
44 | }
45 |
46 | @Test
47 | public void constructFromClock() {
48 | Clock fixedClock = Clock.fixed(DATE_TIME_INSTANT, UTC);
49 | MockClock mockClock = MockClock.at(fixedClock);
50 |
51 | assertClockInstant(mockClock, DATE_TIME_INSTANT);
52 | }
53 |
54 | @Test
55 | public void constructFromInstant() {
56 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
57 |
58 | assertClockInstant(mockClock, DATE_TIME_INSTANT);
59 | }
60 |
61 | @Test
62 | public void constructFromZonedDateTime() {
63 | ZonedDateTime zonedDateTime = LOCAL_DATE_TIME.atZone(UTC);
64 | MockClock mockClock = MockClock.at(zonedDateTime);
65 |
66 | assertClockInstant(mockClock, DATE_TIME_INSTANT);
67 | }
68 |
69 | @Test
70 | public void constructFromLocalDateTime() {
71 | MockClock mockClock = MockClock.at(LOCAL_DATE_TIME, UTC);
72 |
73 | assertClockInstant(mockClock, DATE_TIME_INSTANT);
74 | }
75 |
76 | @Test
77 | public void constructFromLocalDate() {
78 | MockClock mockClock = MockClock.at(LOCAL_DATE, UTC);
79 |
80 | assertClockInstant(mockClock, DATE_ONLY_INSTANT);
81 | }
82 |
83 | @Test
84 | public void constructFromLocalDateAndLocalTime() {
85 | MockClock mockClock = MockClock.at(LOCAL_DATE, LOCAL_TIME, UTC);
86 |
87 | assertClockInstant(mockClock, DATE_TIME_INSTANT);
88 | }
89 |
90 | @Test
91 | public void constructFromFullDateAndTimeWithNanoResolution() {
92 | MockClock mockClock = MockClock.at(YEAR, DECEMBER, DAY_OF_MONTH, HOUR, MINUTE, SECOND, NANO_OF_SECOND, UTC);
93 |
94 | assertClockInstant(mockClock, DATE_TIME_INSTANT);
95 | }
96 |
97 | @Test
98 | public void constructFromFullDateAndTimeWithSecondResolution() {
99 | MockClock mockClock = MockClock.at(YEAR, DECEMBER, DAY_OF_MONTH, HOUR, MINUTE, SECOND, UTC);
100 |
101 | assertClockInstant(mockClock, DATE_TIME_INSTANT.minusNanos(NANO_OF_SECOND));
102 | }
103 |
104 | @Test
105 | public void constructFromFullDateAndTimeWithMinuteResolution() {
106 | MockClock mockClock = MockClock.at(YEAR, DECEMBER, DAY_OF_MONTH, HOUR, MINUTE, UTC);
107 |
108 | assertClockInstant(mockClock, DATE_TIME_INSTANT.minusNanos(NANO_OF_SECOND).minusSeconds(SECOND));
109 | }
110 |
111 | @Test
112 | public void constructFromFullDate() {
113 | MockClock mockClock = MockClock.at(YEAR, DECEMBER, DAY_OF_MONTH, UTC);
114 |
115 | assertClockInstant(mockClock, DATE_ONLY_INSTANT);
116 | }
117 |
118 | @Test
119 | public void constructFromFullDateAndTimeWithIntegerMonthAndNanoResolution() {
120 | MockClock mockClock = MockClock.at(YEAR, 12, DAY_OF_MONTH, HOUR, MINUTE, SECOND, NANO_OF_SECOND, UTC);
121 |
122 | assertClockInstant(mockClock, DATE_TIME_INSTANT);
123 | }
124 |
125 | @Test
126 | public void constructFromFullDateAndTimeWithIntegerMonthAndSecondResolution() {
127 | MockClock mockClock = MockClock.at(YEAR, 12, DAY_OF_MONTH, HOUR, MINUTE, SECOND, UTC);
128 |
129 | assertClockInstant(mockClock, DATE_TIME_INSTANT.minusNanos(NANO_OF_SECOND));
130 | }
131 |
132 | @Test
133 | public void constructFromFullDateAndTimeWithIntegerMonthAndMinuteResolution() {
134 | MockClock mockClock = MockClock.at(YEAR, 12, DAY_OF_MONTH, HOUR, MINUTE, UTC);
135 |
136 | assertClockInstant(mockClock, DATE_TIME_INSTANT.minusNanos(NANO_OF_SECOND).minusSeconds(SECOND));
137 | }
138 |
139 | @Test
140 | public void constructFromFullDateWithIntegerMonth() {
141 | MockClock mockClock = MockClock.at(YEAR, 12, DAY_OF_MONTH, UTC);
142 |
143 | assertClockInstant(mockClock, DATE_ONLY_INSTANT);
144 | }
145 |
146 | @Test
147 | public void adjustWithInstant() {
148 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
149 | Instant adjustedInstant = ZonedDateTime.of(2016, 1, 4, 9, 30, 13, 212, UTC).toInstant();
150 |
151 | mockClock.set(adjustedInstant);
152 |
153 | assertClockInstant(mockClock, adjustedInstant);
154 | }
155 |
156 | @Test
157 | public void adjustWithLocalDateTime() {
158 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
159 | LocalDateTime adjustedLocalDateTime = LocalDateTime.of(2016, 1, 4, 9, 30, 13, 212);
160 | Instant adjustedInstant = ZonedDateTime.of(adjustedLocalDateTime, UTC).toInstant();
161 |
162 | mockClock.set(adjustedLocalDateTime);
163 |
164 | assertClockInstant(mockClock, adjustedInstant);
165 | }
166 |
167 | @Test
168 | public void adjustWithLocalDateAndLocalTime() {
169 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
170 | LocalDate adjustedLocalDate = LocalDate.of(2016, 1, 4);
171 | LocalTime adjustedLocalTime = LocalTime.of(9, 30, 13, 212);
172 | Instant adjustedInstant = ZonedDateTime.of(adjustedLocalDate, adjustedLocalTime, UTC).toInstant();
173 |
174 | mockClock.set(adjustedLocalDate, adjustedLocalTime);
175 |
176 | assertClockInstant(mockClock, adjustedInstant);
177 | }
178 |
179 | @Test
180 | public void adjustWithLocalDateLeavingTimeUnchanged() {
181 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
182 | LocalDate adjustedLocalDate = LocalDate.of(2016, 1, 4);
183 | Instant adjustedInstant = ZonedDateTime.of(adjustedLocalDate, LOCAL_TIME, UTC).toInstant();
184 |
185 | mockClock.set(adjustedLocalDate);
186 |
187 | assertClockInstant(mockClock, adjustedInstant);
188 | }
189 |
190 | @Test
191 | public void adjustWithLocalTimeLeavingDateUnchanged() {
192 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
193 | LocalTime adjustedLocalTime = LocalTime.of(9, 30, 13, 212);
194 | Instant adjustedInstant = ZonedDateTime.of(LOCAL_DATE, adjustedLocalTime, UTC).toInstant();
195 |
196 | mockClock.set(adjustedLocalTime);
197 |
198 | assertClockInstant(mockClock, adjustedInstant);
199 | }
200 |
201 | @Test
202 | public void adjustWithFullDateAndTimeWithNanoResolution() {
203 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
204 | Instant adjustedInstant = ZonedDateTime.of(2016, 1, 4, 9, 30, 13, 212, UTC).toInstant();
205 |
206 | mockClock.set(2016, JANUARY, 4, 9, 30, 13, 212);
207 |
208 | assertClockInstant(mockClock, adjustedInstant);
209 | }
210 |
211 | @Test
212 | public void adjustWithFullDateAndTimeWithSecondResolutionLeavingNanoUnchanged() {
213 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
214 | Instant adjustedInstant = ZonedDateTime.of(2016, 1, 4, 9, 30, 13, NANO_OF_SECOND, UTC).toInstant();
215 |
216 | mockClock.set(2016, JANUARY, 4, 9, 30, 13);
217 |
218 | assertClockInstant(mockClock, adjustedInstant);
219 | }
220 |
221 | @Test
222 | public void adjustWithFullDateAndTimeWithMinuteResolutionLeavingSecondAndNanoUnchanged() {
223 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
224 | Instant adjustedInstant = ZonedDateTime.of(2016, 1, 4, 9, 30, SECOND, NANO_OF_SECOND, UTC).toInstant();
225 |
226 | mockClock.set(2016, JANUARY, 4, 9, 30);
227 |
228 | assertClockInstant(mockClock, adjustedInstant);
229 | }
230 |
231 | @Test
232 | public void adjustWithFullDateLeavingTimeUnchanged() {
233 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
234 | Instant adjustedInstant = ZonedDateTime.of(2016, 1, 4, HOUR, MINUTE, SECOND, NANO_OF_SECOND, UTC).toInstant();
235 |
236 | mockClock.set(2016, JANUARY, 4);
237 |
238 | assertClockInstant(mockClock, adjustedInstant);
239 | }
240 |
241 | @Test
242 | public void adjustWithFullDateAndTimeWithIntegerMonthAndNanoResolution() {
243 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
244 | Instant adjustedInstant = ZonedDateTime.of(2016, 1, 4, 9, 30, 13, 212, UTC).toInstant();
245 |
246 | mockClock.set(2016, 1, 4, 9, 30, 13, 212);
247 |
248 | assertClockInstant(mockClock, adjustedInstant);
249 | }
250 |
251 | @Test
252 | public void adjustWithFullDateAndTimeWithIntegerMonthAndSecondResolutionLeavingNanoUnchanged() {
253 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
254 | Instant adjustedInstant = ZonedDateTime.of(2016, 1, 4, 9, 30, 13, NANO_OF_SECOND, UTC).toInstant();
255 |
256 | mockClock.set(2016, 1, 4, 9, 30, 13);
257 |
258 | assertClockInstant(mockClock, adjustedInstant);
259 | }
260 |
261 | @Test
262 | public void adjustWithFullDateAndTimeWithIntegerMonthAndMinuteResolutionLeavingSecondAndNanoUnchanged() {
263 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
264 | Instant adjustedInstant = ZonedDateTime.of(2016, 1, 4, 9, 30, SECOND, NANO_OF_SECOND, UTC).toInstant();
265 |
266 | mockClock.set(2016, 1, 4, 9, 30);
267 |
268 | assertClockInstant(mockClock, adjustedInstant);
269 | }
270 |
271 | @Test
272 | public void adjustWithFullDateAndIntegerMonthLeavingTimeUnchanged() {
273 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
274 | Instant adjustedInstant = ZonedDateTime.of(2016, 1, 4, HOUR, MINUTE, SECOND, NANO_OF_SECOND, UTC).toInstant();
275 |
276 | mockClock.set(2016, 1, 4);
277 |
278 | assertClockInstant(mockClock, adjustedInstant);
279 | }
280 |
281 | @Test
282 | public void adjustWithYear() {
283 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
284 | Instant adjustedInstant = ZonedDateTime
285 | .of(2017, MONTH.getValue(), DAY_OF_MONTH, HOUR, MINUTE, SECOND, NANO_OF_SECOND, UTC).toInstant();
286 |
287 | mockClock.setYear(2017);
288 |
289 | assertClockInstant(mockClock, adjustedInstant);
290 | }
291 |
292 | @Test
293 | public void adjustWithMonth() {
294 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
295 | Instant adjustedInstant = ZonedDateTime
296 | .of(YEAR, JANUARY.getValue(), DAY_OF_MONTH, HOUR, MINUTE, SECOND, NANO_OF_SECOND, UTC).toInstant();
297 |
298 | mockClock.setMonth(JANUARY);
299 |
300 | assertClockInstant(mockClock, adjustedInstant);
301 | }
302 |
303 | @Test
304 | public void adjustWithIntegerMonth() {
305 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
306 | Instant adjustedInstant = ZonedDateTime
307 | .of(YEAR, JANUARY.getValue(), DAY_OF_MONTH, HOUR, MINUTE, SECOND, NANO_OF_SECOND, UTC).toInstant();
308 |
309 | mockClock.setMonth(1);
310 |
311 | assertClockInstant(mockClock, adjustedInstant);
312 | }
313 |
314 | @Test
315 | public void adjustWithDayOfMonth() {
316 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
317 | Instant adjustedInstant = ZonedDateTime
318 | .of(YEAR, MONTH.getValue(), 17, HOUR, MINUTE, SECOND, NANO_OF_SECOND, UTC).toInstant();
319 |
320 | mockClock.setDayOfMonth(17);
321 |
322 | assertClockInstant(mockClock, adjustedInstant);
323 | }
324 |
325 | @Test
326 | public void adjustWithHour() {
327 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
328 | Instant adjustedInstant = ZonedDateTime
329 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH, 9, MINUTE, SECOND, NANO_OF_SECOND, UTC).toInstant();
330 |
331 | mockClock.setHour(9);
332 |
333 | assertClockInstant(mockClock, adjustedInstant);
334 | }
335 |
336 | @Test
337 | public void adjustWithMinute() {
338 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
339 | Instant adjustedInstant = ZonedDateTime
340 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR, 30, SECOND, NANO_OF_SECOND, UTC).toInstant();
341 |
342 | mockClock.setMinute(30);
343 |
344 | assertClockInstant(mockClock, adjustedInstant);
345 | }
346 |
347 | @Test
348 | public void adjustWithSecond() {
349 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
350 | Instant adjustedInstant = ZonedDateTime
351 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR, MINUTE, 13, NANO_OF_SECOND, UTC).toInstant();
352 |
353 | mockClock.setSecond(13);
354 |
355 | assertClockInstant(mockClock, adjustedInstant);
356 | }
357 |
358 | @Test
359 | public void adjustWithMilli() {
360 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
361 | int nanoOfSecond = 400_000_000;
362 | Instant adjustedInstant = ZonedDateTime.of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR, MINUTE, SECOND,
363 | nanoOfSecond, UTC).toInstant();
364 |
365 | mockClock.setMilli(400);
366 |
367 | assertClockInstant(mockClock, adjustedInstant);
368 | }
369 |
370 | @Test
371 | public void adjustWithNano() {
372 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
373 | Instant adjustedInstant = ZonedDateTime.of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR, MINUTE, SECOND, 212, UTC)
374 | .toInstant();
375 |
376 | mockClock.setNano(212);
377 |
378 | assertClockInstant(mockClock, adjustedInstant);
379 | }
380 |
381 | @Test
382 | public void advanceByDuration() {
383 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
384 | Instant adjustedInstant = ZonedDateTime
385 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR, MINUTE, SECOND + 10, NANO_OF_SECOND, UTC).toInstant();
386 |
387 | mockClock.advanceBy(Duration.ofSeconds(10));
388 |
389 | assertClockInstant(mockClock, adjustedInstant);
390 | }
391 |
392 | @Test
393 | public void advanceByDays() {
394 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
395 | Instant adjustedInstant = ZonedDateTime
396 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH + 3, HOUR, MINUTE, SECOND, NANO_OF_SECOND, UTC).toInstant();
397 |
398 | mockClock.advanceByDays(3);
399 |
400 | assertClockInstant(mockClock, adjustedInstant);
401 | }
402 |
403 | @Test
404 | public void advanceByHours() {
405 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
406 | Instant adjustedInstant = ZonedDateTime
407 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR + 2, MINUTE, SECOND, NANO_OF_SECOND, UTC).toInstant();
408 |
409 | mockClock.advanceByHours(2);
410 |
411 | assertClockInstant(mockClock, adjustedInstant);
412 | }
413 |
414 | @Test
415 | public void advanceByMinutes() {
416 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
417 | Instant adjustedInstant = ZonedDateTime
418 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR, MINUTE + 4, SECOND, NANO_OF_SECOND, UTC).toInstant();
419 |
420 | mockClock.advanceByMinutes(4);
421 |
422 | assertClockInstant(mockClock, adjustedInstant);
423 | }
424 |
425 | @Test
426 | public void advanceBySeconds() {
427 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
428 | Instant adjustedInstant = ZonedDateTime
429 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR, MINUTE, SECOND + 5, NANO_OF_SECOND, UTC).toInstant();
430 |
431 | mockClock.advanceBySeconds(5);
432 |
433 | assertClockInstant(mockClock, adjustedInstant);
434 | }
435 |
436 | @Test
437 | public void advanceByMillis() {
438 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
439 | int nanoOfSecond = NANO_OF_SECOND + 400_000_000;
440 | Instant adjustedInstant = ZonedDateTime
441 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR, MINUTE, SECOND, nanoOfSecond, UTC).toInstant();
442 |
443 | mockClock.advanceByMillis(400);
444 |
445 | assertClockInstant(mockClock, adjustedInstant);
446 | }
447 |
448 | @Test
449 | public void advanceByNanos() {
450 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
451 | Instant adjustedInstant = ZonedDateTime
452 | .of(YEAR, MONTH.getValue(), DAY_OF_MONTH, HOUR, MINUTE, SECOND, NANO_OF_SECOND + 1000, UTC).toInstant();
453 |
454 | mockClock.advanceByNanos(1000);
455 |
456 | assertClockInstant(mockClock, adjustedInstant);
457 | }
458 |
459 | @Test
460 | public void withZoneCopyHasSameInstantButDifferentZone() {
461 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
462 | ZoneId cet = ZoneId.of("CET");
463 |
464 | MockClock copied = mockClock.withZone(cet);
465 |
466 | assertClockInstant(copied, DATE_TIME_INSTANT, cet);
467 | }
468 |
469 | @Test
470 | public void sameConstructorParametersYieldEqualInstances() {
471 | MockClock mockClock1 = MockClock.at(DATE_TIME_INSTANT, UTC);
472 | MockClock mockClock2 = MockClock.at(DATE_TIME_INSTANT, UTC);
473 |
474 | assertThat(mockClock1.equals(mockClock2), is(true));
475 | }
476 |
477 | @Test
478 | public void sameInstancesAreEqual() {
479 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
480 |
481 | assertThat(mockClock.equals(mockClock), is(true));
482 | }
483 |
484 | @Test
485 | public void nullInstanceIsNotEqual() {
486 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
487 |
488 | assertThat(mockClock.equals(null), is(false));
489 | }
490 |
491 | @Test
492 | public void instanceOfDifferentClassIsNotEqual() {
493 | MockClock mockClock = MockClock.at(DATE_TIME_INSTANT, UTC);
494 |
495 | assertThat(mockClock.equals(Clock.systemUTC()), is(false));
496 | }
497 |
498 | @Test
499 | public void clockWithDifferentInstantIsNotEqual() {
500 | MockClock mockClock1 = MockClock.at(DATE_TIME_INSTANT, UTC);
501 | MockClock mockClock2 = MockClock.at(DATE_ONLY_INSTANT, UTC);
502 |
503 | assertThat(mockClock1.equals(mockClock2), is(false));
504 | }
505 |
506 | @Test
507 | public void clockWithDifferentZoneIsNotEqual() {
508 | MockClock mockClock1 = MockClock.at(DATE_TIME_INSTANT, UTC);
509 | MockClock mockClock2 = MockClock.at(DATE_TIME_INSTANT, ZoneId.of("CET"));
510 |
511 | assertThat(mockClock1.equals(mockClock2), is(false));
512 | }
513 |
514 | @Test
515 | public void sameConstructorParametersYieldEqualHashCodes() {
516 | MockClock mockClock1 = MockClock.at(DATE_TIME_INSTANT, UTC);
517 | MockClock mockClock2 = MockClock.at(DATE_TIME_INSTANT, UTC);
518 |
519 | assertThat(mockClock1.hashCode(), is(mockClock2.hashCode()));
520 | }
521 |
522 | @Test
523 | public void sameConstructorParametersYieldEqualStringRepresentations() {
524 | MockClock mockClock1 = MockClock.at(DATE_TIME_INSTANT, UTC);
525 | MockClock mockClock2 = MockClock.at(DATE_TIME_INSTANT, UTC);
526 |
527 | assertThat(mockClock1.toString(), is(mockClock2.toString()));
528 | }
529 |
530 | private void assertClockInstant(MockClock mockClock, Instant instant) {
531 | assertClockInstant(mockClock, instant, UTC);
532 | }
533 |
534 | private void assertClockInstant(MockClock mockClock, Instant instant, ZoneId zone) {
535 | assertThat(mockClock.instant(), is(instant));
536 | assertThat(mockClock.getZone(), is(zone));
537 | }
538 | }
539 |
--------------------------------------------------------------------------------
/src/main/java/com/statemachinesystems/mockclock/MockClock.java:
--------------------------------------------------------------------------------
1 | package com.statemachinesystems.mockclock;
2 |
3 | import java.time.Clock;
4 | import java.time.Duration;
5 | import java.time.Instant;
6 | import java.time.LocalDate;
7 | import java.time.LocalDateTime;
8 | import java.time.LocalTime;
9 | import java.time.Month;
10 | import java.time.ZoneId;
11 | import java.time.ZonedDateTime;
12 | import java.util.Objects;
13 | import java.util.concurrent.TimeUnit;
14 |
15 | /**
16 | * Mutable implementation of {@link java.time.Clock} for testing.
17 | */
18 | public class MockClock extends Clock {
19 |
20 | /**
21 | * Construct a {@link MockClock} using the current time in the given zone.
22 | *
23 | * @param zone the zone to use
24 | * @return a {@link MockClock} instance initially set to the current time in the given zone
25 | */
26 | public static MockClock now(ZoneId zone) {
27 | return at(Clock.system(zone));
28 | }
29 |
30 | /**
31 | * Construct a {@link MockClock} using the current time according to the given clock.
32 | *
33 | * @param clock the clock to use
34 | * @return a {@link MockClock} instance initially set to the current time according to the given clock
35 | */
36 | public static MockClock at(Clock clock) {
37 | Objects.requireNonNull(clock, "clock");
38 | return new MockClock(clock.instant(), clock.getZone());
39 | }
40 |
41 | /**
42 | * Construct a {@link MockClock} using the given {@link Instant} and zone.
43 | *
44 | * @param instant the {@link Instant} to use
45 | * @param zone the zone to use
46 | * @return a {@link MockClock} instance initially set to the given {@link Instant} and zone
47 | */
48 | public static MockClock at(Instant instant, ZoneId zone) {
49 | Objects.requireNonNull(instant, "instant");
50 | Objects.requireNonNull(zone, "zone");
51 | return new MockClock(instant, zone);
52 | }
53 |
54 | /**
55 | * Construct a {@link MockClock} using the given {@link ZonedDateTime}.
56 | *
57 | * @param zonedDateTime the {@link ZonedDateTime} to use
58 | * @return a {@link MockClock} instance initially set to the given {@link ZonedDateTime}
59 | */
60 | public static MockClock at(ZonedDateTime zonedDateTime) {
61 | Objects.requireNonNull(zonedDateTime, "zonedDateTime");
62 | return at(zonedDateTime.toInstant(), zonedDateTime.getZone());
63 | }
64 |
65 | /**
66 | * Construct a {@link MockClock} using the given {@link LocalDateTime} and zone.
67 | *
68 | * @param localDateTime the {@link LocalDateTime} to use
69 | * @param zone the zone to use
70 | * @return a {@link MockClock} instance initially set to the given {@link LocalDateTime} and zone
71 | */
72 | public static MockClock at(LocalDateTime localDateTime, ZoneId zone) {
73 | Objects.requireNonNull(localDateTime, "localDateTime");
74 | Objects.requireNonNull(zone, "zone");
75 | return at(localDateTime.atZone(zone));
76 | }
77 |
78 | /**
79 | * Construct a {@link MockClock} using the given date and zone.
80 | *
81 | * @param localDate the date to use
82 | * @param zone the zone to use
83 | * @return a {@link MockClock} instance initially set to the given date and zone
84 | */
85 | public static MockClock at(LocalDate localDate, ZoneId zone) {
86 | Objects.requireNonNull(localDate, "localDate");
87 | Objects.requireNonNull(zone, "zone");
88 | return at(localDate.atStartOfDay(zone));
89 | }
90 |
91 | /**
92 | * Construct a {@link MockClock} using the given date, time and zone.
93 | *
94 | * @param localDate the date to use
95 | * @param localTime the time to use
96 | * @param zone the zone to use
97 | * @return a {@link MockClock} instance initially set to the given date, time and zone
98 | */
99 | public static MockClock at(LocalDate localDate, LocalTime localTime, ZoneId zone) {
100 | Objects.requireNonNull(localDate, "localDate");
101 | Objects.requireNonNull(localTime, "localTime");
102 | Objects.requireNonNull(zone, "zone");
103 | return at(LocalDateTime.of(localDate, localTime), zone);
104 | }
105 |
106 | /**
107 | * Construct a {@link MockClock} using the given year, month, day of month, hour, minute, second, nanosecond and
108 | * zone.
109 | *
110 | * @param year the year to use
111 | * @param month the month to use
112 | * @param dayOfMonth the day of month to use
113 | * @param hour the hour to use
114 | * @param minute the minute to use
115 | * @param second the second to use
116 | * @param nanoOfSecond the nanosecond to use
117 | * @param zone the zone to use
118 | * @return a {@link MockClock} instance initially set to the given year, month, day of month, hour, minute, second,
119 | * nanosecond and zone
120 | */
121 | public static MockClock at(int year, Month month, int dayOfMonth, int hour, int minute, int second,
122 | int nanoOfSecond, ZoneId zone) {
123 | Objects.requireNonNull(month, "month");
124 | Objects.requireNonNull(zone, "zone");
125 | return at(LocalDate.of(year, month, dayOfMonth), LocalTime.of(hour, minute, second, nanoOfSecond), zone);
126 | }
127 |
128 | /**
129 | * Construct a {@link MockClock} using the given year, month, day of month, hour, minute, second and zone.
130 | *
131 | * @param year the year to use
132 | * @param month the month to use
133 | * @param dayOfMonth the day of month to use
134 | * @param hour the hour to use
135 | * @param minute the minute to use
136 | * @param second the second to use
137 | * @param zone the zone to use
138 | * @return a {@link MockClock} instance initially set to the given year, month, day of month, hour, minute, second
139 | * and zone
140 | */
141 | public static MockClock at(int year, Month month, int dayOfMonth, int hour, int minute, int second, ZoneId zone) {
142 | Objects.requireNonNull(month, "month");
143 | Objects.requireNonNull(zone, "zone");
144 | return at(LocalDate.of(year, month, dayOfMonth), LocalTime.of(hour, minute, second), zone);
145 | }
146 |
147 | /**
148 | * Construct a {@link MockClock} using the given year, month, day of month, hour, minute and zone.
149 | *
150 | * @param year the year to use
151 | * @param month the month to use
152 | * @param dayOfMonth the day of month to use
153 | * @param hour the hour to use
154 | * @param minute the minute to use
155 | * @param zone the zone to use
156 | * @return a {@link MockClock} instance initially set to the given year, month, day of month, hour, minute and zone
157 | */
158 | public static MockClock at(int year, Month month, int dayOfMonth, int hour, int minute, ZoneId zone) {
159 | Objects.requireNonNull(month, "month");
160 | Objects.requireNonNull(zone, "zone");
161 | return at(LocalDate.of(year, month, dayOfMonth), LocalTime.of(hour, minute), zone);
162 | }
163 |
164 | /**
165 | * Construct a {@link MockClock} using the given year, month, day of month and zone.
166 | *
167 | * @param year the year to use
168 | * @param month the month to use
169 | * @param dayOfMonth the day of month to use
170 | * @param zone the zone to use
171 | * @return a {@link MockClock} instance initially set to the given year, month, day of month and zone
172 | */
173 | public static MockClock at(int year, Month month, int dayOfMonth, ZoneId zone) {
174 | Objects.requireNonNull(month, "month");
175 | Objects.requireNonNull(zone, "zone");
176 | return at(LocalDate.of(year, month, dayOfMonth), zone);
177 | }
178 |
179 | /**
180 | * Construct a {@link MockClock} using the given year, month, day of month, hour, minute, second, nanosecond and
181 | * zone.
182 | *
183 | * @param year the year to use
184 | * @param month the month to use
185 | * @param dayOfMonth the day of month to use
186 | * @param hour the hour to use
187 | * @param minute the minute to use
188 | * @param second the second to use
189 | * @param nanoOfSecond the nanosecond to use
190 | * @param zone the zone to use
191 | * @return a {@link MockClock} instance initially set to the given year, month, day of month, hour, minute, second,
192 | * nanosecond and zone
193 | */
194 | public static MockClock at(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond,
195 | ZoneId zone) {
196 | Objects.requireNonNull(zone, "zone");
197 | return at(LocalDate.of(year, month, dayOfMonth), LocalTime.of(hour, minute, second, nanoOfSecond), zone);
198 | }
199 |
200 | /**
201 | * Construct a {@link MockClock} using the given year, month, day of month, hour, minute, second and zone.
202 | *
203 | * @param year the year to use
204 | * @param month the month to use
205 | * @param dayOfMonth the day of month to use
206 | * @param hour the hour to use
207 | * @param minute the minute to use
208 | * @param second the second to use
209 | * @param zone the zone to use
210 | * @return a {@link MockClock} instance initially set to the given year, month, day of month, hour, minute, second
211 | * and zone
212 | */
213 | public static MockClock at(int year, int month, int dayOfMonth, int hour, int minute, int second, ZoneId zone) {
214 | Objects.requireNonNull(zone, "zone");
215 | return at(LocalDate.of(year, month, dayOfMonth), LocalTime.of(hour, minute, second), zone);
216 | }
217 |
218 | /**
219 | * Construct a {@link MockClock} using the given year, month, day of month, hour, minute and zone.
220 | *
221 | * @param year the year to use
222 | * @param month the month to use
223 | * @param dayOfMonth the day of month to use
224 | * @param hour the hour to use
225 | * @param minute the minute to use
226 | * @param zone the zone to use
227 | * @return a {@link MockClock} instance initially set to the given year, month, day of month, hour, minute and zone
228 | */
229 | public static MockClock at(int year, int month, int dayOfMonth, int hour, int minute, ZoneId zone) {
230 | Objects.requireNonNull(zone, "zone");
231 | return at(LocalDate.of(year, month, dayOfMonth), LocalTime.of(hour, minute), zone);
232 | }
233 |
234 | /**
235 | * Construct a {@link MockClock} using the given year, month, day of month and zone.
236 | *
237 | * @param year the year to use
238 | * @param month the month to use
239 | * @param dayOfMonth the day of month to use
240 | * @param zone the zone to use
241 | * @return a {@link MockClock} instance initially set to the given year, month, day of month and zone
242 | */
243 | public static MockClock at(int year, int month, int dayOfMonth, ZoneId zone) {
244 | Objects.requireNonNull(zone, "zone");
245 | return at(LocalDate.of(year, month, dayOfMonth), zone);
246 | }
247 |
248 | private Instant instant;
249 | private final ZoneId zone;
250 |
251 | private MockClock(Instant instant, ZoneId zone) {
252 | this.instant = instant;
253 | this.zone = zone;
254 | }
255 |
256 | /**
257 | * Set the clock's date and time to the given {@link Instant}.
258 | *
259 | * @param instant the {@link Instant} to use
260 | * @return this {@link MockClock} instance
261 | */
262 | public MockClock set(Instant instant) {
263 | Objects.requireNonNull(instant, "instant");
264 | this.instant = instant;
265 | return this;
266 | }
267 |
268 | /**
269 | * Set the clock's date and time using the given {@link LocalDateTime}.
270 | *
271 | * @param localDateTime the {@link LocalDateTime} to use
272 | * @return this {@link MockClock} instance
273 | */
274 | public MockClock set(LocalDateTime localDateTime) {
275 | Objects.requireNonNull(localDateTime, "localDateTime");
276 | this.instant = localDateTime.atZone(zone).toInstant();
277 | return this;
278 | }
279 |
280 | /**
281 | * Set the clock's date and time using the given {@link LocalDate} and {@link LocalTime}.
282 | *
283 | * @param localDate the {@link LocalDate} to use
284 | * @param localTime the {@link LocalTime} to use
285 | * @return this {@link MockClock} instance
286 | */
287 | public MockClock set(LocalDate localDate, LocalTime localTime) {
288 | Objects.requireNonNull(localDate, "localDate");
289 | Objects.requireNonNull(localTime, "localTime");
290 | this.instant = ZonedDateTime.of(localDate, localTime, zone).toInstant();
291 | return this;
292 | }
293 |
294 | /**
295 | * Set the clock's date using the given {@link LocalDate}, retaining the current time.
296 | *
297 | * @param localDate the {@link LocalDate} to use
298 | * @return this {@link MockClock} instance
299 | */
300 | public MockClock set(LocalDate localDate) {
301 | Objects.requireNonNull(localDate, "localDate");
302 | LocalTime localTime = toZonedDateTime().toLocalTime();
303 | this.instant = ZonedDateTime.of(localDate, localTime, zone).toInstant();
304 | return this;
305 | }
306 |
307 | /**
308 | * Set the clock's time using the given {@link LocalTime}, retaining the current date.
309 | *
310 | * @param localTime the {@link LocalTime} to use
311 | * @return this {@link MockClock} instance
312 | */
313 | public MockClock set(LocalTime localTime) {
314 | Objects.requireNonNull(localTime, "localTime");
315 | LocalDate localDate = toZonedDateTime().toLocalDate();
316 | this.instant = ZonedDateTime.of(localDate, localTime, zone).toInstant();
317 | return this;
318 | }
319 |
320 | /**
321 | * Set the clock's date and time using the given year, month, day of month, hour, minute, second and nanosecond.
322 | *
323 | * @param year the year to use
324 | * @param month the month to use
325 | * @param dayOfMonth the day of month to use
326 | * @param hour the hour to use
327 | * @param minute the minute to use
328 | * @param second the second to use
329 | * @param nanoOfSecond the nanosecond to use
330 | * @return this {@link MockClock} instance
331 | */
332 | public MockClock set(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) {
333 | Objects.requireNonNull(month, "month");
334 | ZonedDateTime zonedDateTime = ZonedDateTime
335 | .of(year, month.getValue(), dayOfMonth, hour, minute, second, nanoOfSecond, zone);
336 | this.instant = zonedDateTime.toInstant();
337 | return this;
338 | }
339 |
340 | /**
341 | * Set the clock's date and time using the given year, month, day of month, hour, minute and second, retaining the
342 | * current nanosecond.
343 | *
344 | * @param year the year to use
345 | * @param month the month to use
346 | * @param dayOfMonth the day of month to use
347 | * @param hour the hour to use
348 | * @param minute the minute to use
349 | * @param second the second to use
350 | * @return this {@link MockClock} instance
351 | */
352 | public MockClock set(int year, Month month, int dayOfMonth, int hour, int minute, int second) {
353 | int nanoOfSecond = toZonedDateTime().getNano();
354 | return set(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);
355 | }
356 |
357 | /**
358 | * Set the clock's date and time using the given year, month, day of month, hour and minute, retaining the
359 | * current second and nanosecond.
360 | *
361 | * @param year the year to use
362 | * @param month the month to use
363 | * @param dayOfMonth the day of month to use
364 | * @param hour the hour to use
365 | * @param minute the minute to use
366 | * @return this {@link MockClock} instance
367 | */
368 | public MockClock set(int year, Month month, int dayOfMonth, int hour, int minute) {
369 | ZonedDateTime zonedDateTime = toZonedDateTime();
370 | int second = zonedDateTime.getSecond();
371 | int nanoOfSecond = zonedDateTime.getNano();
372 | return set(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);
373 | }
374 |
375 | /**
376 | * Set the clock's date using the given year, month and day of month, retaining the current time.
377 | *
378 | * @param year the year to use
379 | * @param month the month to use
380 | * @param dayOfMonth the day of month to use
381 | * @return this {@link MockClock} instance
382 | */
383 | public MockClock set(int year, Month month, int dayOfMonth) {
384 | ZonedDateTime zonedDateTime = toZonedDateTime();
385 | int hour = zonedDateTime.getHour();
386 | int minute = zonedDateTime.getMinute();
387 | int second = zonedDateTime.getSecond();
388 | int nanoOfSecond = zonedDateTime.getNano();
389 | return set(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);
390 | }
391 |
392 | /**
393 | * Set the clock's date and time using the given year, month, day of month, hour, minute, second and nanosecond.
394 | *
395 | * @param year the year to use
396 | * @param month the month to use
397 | * @param dayOfMonth the day of month to use
398 | * @param hour the hour to use
399 | * @param minute the minute to use
400 | * @param second the second to use
401 | * @param nanoOfSecond the nanosecond to use
402 | * @return this {@link MockClock} instance
403 | */
404 | public MockClock set(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) {
405 | return set(year, Month.of(month), dayOfMonth, hour, minute, second, nanoOfSecond);
406 | }
407 |
408 | /**
409 | * Set the clock's date and time using the given year, month, day of month, hour, minute and second, retaining the
410 | * current nanosecond.
411 | *
412 | * @param year the year to use
413 | * @param month the month to use
414 | * @param dayOfMonth the day of month to use
415 | * @param hour the hour to use
416 | * @param minute the minute to use
417 | * @param second the second to use
418 | * @return this {@link MockClock} instance
419 | */
420 | public MockClock set(int year, int month, int dayOfMonth, int hour, int minute, int second) {
421 | return set(year, Month.of(month), dayOfMonth, hour, minute, second);
422 | }
423 |
424 | /**
425 | * Set the clock's date and time using the given year, month, day of month, hour and minute, retaining the
426 | * current second and nanosecond.
427 | *
428 | * @param year the year to use
429 | * @param month the month to use
430 | * @param dayOfMonth the day of month to use
431 | * @param hour the hour to use
432 | * @param minute the minute to use
433 | * @return this {@link MockClock} instance
434 | */
435 | public MockClock set(int year, int month, int dayOfMonth, int hour, int minute) {
436 | return set(year, Month.of(month), dayOfMonth, hour, minute);
437 | }
438 |
439 | /**
440 | * Set the clock's date using the given year, month and day of month, retaining the current time.
441 | *
442 | * @param year the year to use
443 | * @param month the month to use
444 | * @param dayOfMonth the day of month to use
445 | * @return this {@link MockClock} instance
446 | */
447 | public MockClock set(int year, int month, int dayOfMonth) {
448 | return set(year, Month.of(month), dayOfMonth);
449 | }
450 |
451 | /**
452 | * Set the clock's year only, retaining all other date and time components.
453 | *
454 | * @param year the year to use
455 | * @return this {@link MockClock} instance
456 | */
457 | public MockClock setYear(int year) {
458 | this.instant = toZonedDateTime().withYear(year).toInstant();
459 | return this;
460 | }
461 |
462 | /**
463 | * Set the clock's month only, retaining all other date and time components.
464 | *
465 | * @param month the month to use
466 | * @return this {@link MockClock} instance
467 | */
468 | public MockClock setMonth(Month month) {
469 | return setMonth(month.getValue());
470 | }
471 |
472 | /**
473 | * Set the clock's month only, retaining all other date and time components.
474 | *
475 | * @param month the month to use
476 | * @return this {@link MockClock} instance
477 | */
478 | public MockClock setMonth(int month) {
479 | this.instant = toZonedDateTime().withMonth(month).toInstant();
480 | return this;
481 | }
482 |
483 | /**
484 | * Set the clock's day of month only, retaining all other date and time components.
485 | *
486 | * @param dayOfMonth the day of month to use
487 | * @return this {@link MockClock} instance
488 | */
489 | public MockClock setDayOfMonth(int dayOfMonth) {
490 | this.instant = toZonedDateTime().withDayOfMonth(dayOfMonth).toInstant();
491 | return this;
492 | }
493 |
494 | /**
495 | * Set the clock's hour only, retaining all other date and time components.
496 | *
497 | * @param hour the hour to use
498 | * @return this {@link MockClock} instance
499 | */
500 | public MockClock setHour(int hour) {
501 | this.instant = toZonedDateTime().withHour(hour).toInstant();
502 | return this;
503 | }
504 |
505 | /**
506 | * Set the clock's minute only, retaining all other date and time components.
507 | *
508 | * @param minute the minute to use
509 | * @return this {@link MockClock} instance
510 | */
511 | public MockClock setMinute(int minute) {
512 | this.instant = toZonedDateTime().withMinute(minute).toInstant();
513 | return this;
514 | }
515 |
516 | /**
517 | * Set the clock's second only, retaining all other date and time components.
518 | *
519 | * @param second the second to use
520 | * @return this {@link MockClock} instance
521 | */
522 | public MockClock setSecond(int second) {
523 | this.instant = toZonedDateTime().withSecond(second).toInstant();
524 | return this;
525 | }
526 |
527 | /**
528 | * Set the clock's millisecond only, retaining all other date and time components.
529 | *
530 | * @param milliOfSecond the millisecond to use
531 | * @return this {@link MockClock} instance
532 | */
533 | public MockClock setMilli(int milliOfSecond) {
534 | int nanoOfSecond = (int) TimeUnit.MILLISECONDS.toNanos(milliOfSecond);
535 | return setNano(nanoOfSecond);
536 | }
537 |
538 | /**
539 | * Set the clock's nanosecond only, retaining all other date and time components.
540 | *
541 | * @param nanoOfSecond the nanosecond to use
542 | * @return this {@link MockClock} instance
543 | */
544 | public MockClock setNano(int nanoOfSecond) {
545 | this.instant = toZonedDateTime().withNano(nanoOfSecond).toInstant();
546 | return this;
547 | }
548 |
549 | /**
550 | * Advance the clock by the given {@link Duration}.
551 | *
552 | * @param duration the duration by which to advance
553 | * @return this {@link MockClock} instance
554 | */
555 | public MockClock advanceBy(Duration duration) {
556 | this.instant = toZonedDateTime().plus(duration).toInstant();
557 | return this;
558 | }
559 |
560 | /**
561 | * Advance the clock by the given number of days (represented as 24 hours.)
562 | *
563 | * @param days the number of days by which to advance
564 | * @return this {@link MockClock} instance
565 | */
566 | public MockClock advanceByDays(int days) {
567 | return advanceBy(Duration.ofDays(days));
568 | }
569 |
570 | /**
571 | * Advance the clock by the given number of hours.
572 | *
573 | * @param hours the number of hours by which to advance
574 | * @return this {@link MockClock} instance
575 | */
576 | public MockClock advanceByHours(int hours) {
577 | return advanceBy(Duration.ofHours(hours));
578 | }
579 |
580 | /**
581 | * Advance the clock by the given number of minutes.
582 | *
583 | * @param minutes the number of minutes by which to advance
584 | * @return this {@link MockClock} instance
585 | */
586 | public MockClock advanceByMinutes(int minutes) {
587 | return advanceBy(Duration.ofMinutes(minutes));
588 | }
589 |
590 | /**
591 | * Advance the clock by the given number of seconds.
592 | *
593 | * @param seconds the number of seconds by which to advance
594 | * @return this {@link MockClock} instance
595 | */
596 | public MockClock advanceBySeconds(int seconds) {
597 | return advanceBy(Duration.ofSeconds(seconds));
598 | }
599 |
600 | /**
601 | * Advance the clock by the given number of milliseconds.
602 | *
603 | * @param millis the number of milliseconds by which to advance
604 | * @return this {@link MockClock} instance
605 | */
606 | public MockClock advanceByMillis(int millis) {
607 | return advanceBy(Duration.ofMillis(millis));
608 | }
609 |
610 | /**
611 | * Advance the clock by the given number of nanoseconds.
612 | *
613 | * @param nanos the number of nanoseconds by which to advance
614 | * @return this {@link MockClock} instance
615 | */
616 | public MockClock advanceByNanos(int nanos) {
617 | return advanceBy(Duration.ofNanos(nanos));
618 | }
619 |
620 | /**
621 | * Retrieve the clock's date and time as a {@link ZonedDateTime}.
622 | *
623 | * @return a {@link ZonedDateTime} representing the clock's current state
624 | */
625 | public ZonedDateTime toZonedDateTime() {
626 | return ZonedDateTime.ofInstant(instant, zone);
627 | }
628 |
629 | @Override
630 | public ZoneId getZone() {
631 | return zone;
632 | }
633 |
634 | @Override
635 | public MockClock withZone(ZoneId zone) {
636 | Objects.requireNonNull(zone, "zone");
637 | return new MockClock(instant, zone);
638 | }
639 |
640 | @Override
641 | public Instant instant() {
642 | return instant;
643 | }
644 |
645 | @Override
646 | public String toString() {
647 | return "MockClock[" + instant + "," + zone + "]";
648 | }
649 |
650 | @Override
651 | public boolean equals(Object o) {
652 | if (this == o) {
653 | return true;
654 | }
655 | if (o == null || getClass() != o.getClass()) {
656 | return false;
657 | }
658 |
659 | MockClock mockClock = (MockClock) o;
660 | return Objects.equals(instant, mockClock.instant) && Objects.equals(zone, mockClock.zone);
661 | }
662 |
663 | @Override
664 | public int hashCode() {
665 | return Objects.hash(instant, zone);
666 | }
667 | }
668 |
--------------------------------------------------------------------------------