Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/time/Clock.java
41152 views
1
/*
2
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
/*
27
* This file is available under and governed by the GNU General Public
28
* License version 2 only, as published by the Free Software Foundation.
29
* However, the following notice accompanied the original version of this
30
* file:
31
*
32
* Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
33
*
34
* All rights reserved.
35
*
36
* Redistribution and use in source and binary forms, with or without
37
* modification, are permitted provided that the following conditions are met:
38
*
39
* * Redistributions of source code must retain the above copyright notice,
40
* this list of conditions and the following disclaimer.
41
*
42
* * Redistributions in binary form must reproduce the above copyright notice,
43
* this list of conditions and the following disclaimer in the documentation
44
* and/or other materials provided with the distribution.
45
*
46
* * Neither the name of JSR-310 nor the names of its contributors
47
* may be used to endorse or promote products derived from this software
48
* without specific prior written permission.
49
*
50
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
54
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
55
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
56
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
57
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
58
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
59
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
60
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61
*/
62
package java.time;
63
64
import java.io.IOException;
65
import java.io.ObjectInputStream;
66
import static java.time.LocalTime.NANOS_PER_MINUTE;
67
import static java.time.LocalTime.NANOS_PER_SECOND;
68
import static java.time.LocalTime.NANOS_PER_MILLI;
69
import java.io.Serializable;
70
import java.util.Objects;
71
import java.util.TimeZone;
72
import jdk.internal.misc.VM;
73
74
/**
75
* A clock providing access to the current instant, date and time using a time-zone.
76
* <p>
77
* Instances of this class are used to find the current instant, which can be
78
* interpreted using the stored time-zone to find the current date and time.
79
* As such, a clock can be used instead of {@link System#currentTimeMillis()}
80
* and {@link TimeZone#getDefault()}.
81
* <p>
82
* Use of a {@code Clock} is optional. All key date-time classes also have a
83
* {@code now()} factory method that uses the system clock in the default time zone.
84
* The primary purpose of this abstraction is to allow alternate clocks to be
85
* plugged in as and when required. Applications use an object to obtain the
86
* current time rather than a static method. This can simplify testing.
87
* <p>
88
* Best practice for applications is to pass a {@code Clock} into any method
89
* that requires the current instant. A dependency injection framework is one
90
* way to achieve this:
91
* <pre>
92
* public class MyBean {
93
* private Clock clock; // dependency inject
94
* ...
95
* public void process(LocalDate eventDate) {
96
* if (eventDate.isBefore(LocalDate.now(clock)) {
97
* ...
98
* }
99
* }
100
* }
101
* </pre>
102
* This approach allows an alternate clock, such as {@link #fixed(Instant, ZoneId) fixed}
103
* or {@link #offset(Clock, Duration) offset} to be used during testing.
104
* <p>
105
* The {@code system} factory methods provide clocks based on the best available
106
* system clock This may use {@link System#currentTimeMillis()}, or a higher
107
* resolution clock if one is available.
108
*
109
* @implSpec
110
* This abstract class must be implemented with care to ensure other classes operate correctly.
111
* All implementations that can be instantiated must be final, immutable and thread-safe.
112
* <p>
113
* The principal methods are defined to allow the throwing of an exception.
114
* In normal use, no exceptions will be thrown, however one possible implementation would be to
115
* obtain the time from a central time server across the network. Obviously, in this case the
116
* lookup could fail, and so the method is permitted to throw an exception.
117
* <p>
118
* The returned instants from {@code Clock} work on a time-scale that ignores leap seconds,
119
* as described in {@link Instant}. If the implementation wraps a source that provides leap
120
* second information, then a mechanism should be used to "smooth" the leap second.
121
* The Java Time-Scale mandates the use of UTC-SLS, however clock implementations may choose
122
* how accurate they are with the time-scale so long as they document how they work.
123
* Implementations are therefore not required to actually perform the UTC-SLS slew or to
124
* otherwise be aware of leap seconds.
125
* <p>
126
* Implementations should implement {@code Serializable} wherever possible and must
127
* document whether or not they do support serialization.
128
*
129
* @implNote
130
* The clock implementation provided here is based on the same underlying clock
131
* as {@link System#currentTimeMillis()}, but may have a precision finer than
132
* milliseconds if available.
133
* However, little to no guarantee is provided about the accuracy of the
134
* underlying clock. Applications requiring a more accurate clock must implement
135
* this abstract class themselves using a different external clock, such as an
136
* NTP server.
137
*
138
* @since 1.8
139
*/
140
public abstract class Clock {
141
142
/**
143
* Obtains a clock that returns the current instant using the best available
144
* system clock, converting to date and time using the UTC time-zone.
145
* <p>
146
* This clock, rather than {@link #systemDefaultZone()}, should be used when
147
* you need the current instant without the date or time.
148
* <p>
149
* This clock is based on the best available system clock.
150
* This may use {@link System#currentTimeMillis()}, or a higher resolution
151
* clock if one is available.
152
* <p>
153
* Conversion from instant to date or time uses the {@linkplain ZoneOffset#UTC UTC time-zone}.
154
* <p>
155
* The returned implementation is immutable, thread-safe and {@code Serializable}.
156
* It is equivalent to {@code system(ZoneOffset.UTC)}.
157
*
158
* @return a clock that uses the best available system clock in the UTC zone, not null
159
*/
160
public static Clock systemUTC() {
161
return SystemClock.UTC;
162
}
163
164
/**
165
* Obtains a clock that returns the current instant using the best available
166
* system clock, converting to date and time using the default time-zone.
167
* <p>
168
* This clock is based on the best available system clock.
169
* This may use {@link System#currentTimeMillis()}, or a higher resolution
170
* clock if one is available.
171
* <p>
172
* Using this method hard codes a dependency to the default time-zone into your application.
173
* It is recommended to avoid this and use a specific time-zone whenever possible.
174
* The {@link #systemUTC() UTC clock} should be used when you need the current instant
175
* without the date or time.
176
* <p>
177
* The returned implementation is immutable, thread-safe and {@code Serializable}.
178
* It is equivalent to {@code system(ZoneId.systemDefault())}.
179
*
180
* @return a clock that uses the best available system clock in the default zone, not null
181
* @see ZoneId#systemDefault()
182
*/
183
public static Clock systemDefaultZone() {
184
return new SystemClock(ZoneId.systemDefault());
185
}
186
187
/**
188
* Obtains a clock that returns the current instant using the best available
189
* system clock.
190
* <p>
191
* This clock is based on the best available system clock.
192
* This may use {@link System#currentTimeMillis()}, or a higher resolution
193
* clock if one is available.
194
* <p>
195
* Conversion from instant to date or time uses the specified time-zone.
196
* <p>
197
* The returned implementation is immutable, thread-safe and {@code Serializable}.
198
*
199
* @param zone the time-zone to use to convert the instant to date-time, not null
200
* @return a clock that uses the best available system clock in the specified zone, not null
201
*/
202
public static Clock system(ZoneId zone) {
203
Objects.requireNonNull(zone, "zone");
204
if (zone == ZoneOffset.UTC) {
205
return SystemClock.UTC;
206
}
207
return new SystemClock(zone);
208
}
209
210
//-------------------------------------------------------------------------
211
/**
212
* Obtains a clock that returns the current instant ticking in whole milliseconds
213
* using the best available system clock.
214
* <p>
215
* This clock will always have the nano-of-second field truncated to milliseconds.
216
* This ensures that the visible time ticks in whole milliseconds.
217
* The underlying clock is the best available system clock, equivalent to
218
* using {@link #system(ZoneId)}.
219
* <p>
220
* Implementations may use a caching strategy for performance reasons.
221
* As such, it is possible that the start of the millisecond observed via this
222
* clock will be later than that observed directly via the underlying clock.
223
* <p>
224
* The returned implementation is immutable, thread-safe and {@code Serializable}.
225
* It is equivalent to {@code tick(system(zone), Duration.ofMillis(1))}.
226
*
227
* @param zone the time-zone to use to convert the instant to date-time, not null
228
* @return a clock that ticks in whole milliseconds using the specified zone, not null
229
* @since 9
230
*/
231
public static Clock tickMillis(ZoneId zone) {
232
return new TickClock(system(zone), NANOS_PER_MILLI);
233
}
234
235
//-------------------------------------------------------------------------
236
/**
237
* Obtains a clock that returns the current instant ticking in whole seconds
238
* using the best available system clock.
239
* <p>
240
* This clock will always have the nano-of-second field set to zero.
241
* This ensures that the visible time ticks in whole seconds.
242
* The underlying clock is the best available system clock, equivalent to
243
* using {@link #system(ZoneId)}.
244
* <p>
245
* Implementations may use a caching strategy for performance reasons.
246
* As such, it is possible that the start of the second observed via this
247
* clock will be later than that observed directly via the underlying clock.
248
* <p>
249
* The returned implementation is immutable, thread-safe and {@code Serializable}.
250
* It is equivalent to {@code tick(system(zone), Duration.ofSeconds(1))}.
251
*
252
* @param zone the time-zone to use to convert the instant to date-time, not null
253
* @return a clock that ticks in whole seconds using the specified zone, not null
254
*/
255
public static Clock tickSeconds(ZoneId zone) {
256
return new TickClock(system(zone), NANOS_PER_SECOND);
257
}
258
259
/**
260
* Obtains a clock that returns the current instant ticking in whole minutes
261
* using the best available system clock.
262
* <p>
263
* This clock will always have the nano-of-second and second-of-minute fields set to zero.
264
* This ensures that the visible time ticks in whole minutes.
265
* The underlying clock is the best available system clock, equivalent to
266
* using {@link #system(ZoneId)}.
267
* <p>
268
* Implementations may use a caching strategy for performance reasons.
269
* As such, it is possible that the start of the minute observed via this
270
* clock will be later than that observed directly via the underlying clock.
271
* <p>
272
* The returned implementation is immutable, thread-safe and {@code Serializable}.
273
* It is equivalent to {@code tick(system(zone), Duration.ofMinutes(1))}.
274
*
275
* @param zone the time-zone to use to convert the instant to date-time, not null
276
* @return a clock that ticks in whole minutes using the specified zone, not null
277
*/
278
public static Clock tickMinutes(ZoneId zone) {
279
return new TickClock(system(zone), NANOS_PER_MINUTE);
280
}
281
282
/**
283
* Obtains a clock that returns instants from the specified clock truncated
284
* to the nearest occurrence of the specified duration.
285
* <p>
286
* This clock will only tick as per the specified duration. Thus, if the duration
287
* is half a second, the clock will return instants truncated to the half second.
288
* <p>
289
* The tick duration must be positive. If it has a part smaller than a whole
290
* millisecond, then the whole duration must divide into one second without
291
* leaving a remainder. All normal tick durations will match these criteria,
292
* including any multiple of hours, minutes, seconds and milliseconds, and
293
* sensible nanosecond durations, such as 20ns, 250,000ns and 500,000ns.
294
* <p>
295
* A duration of zero or one nanosecond would have no truncation effect.
296
* Passing one of these will return the underlying clock.
297
* <p>
298
* Implementations may use a caching strategy for performance reasons.
299
* As such, it is possible that the start of the requested duration observed
300
* via this clock will be later than that observed directly via the underlying clock.
301
* <p>
302
* The returned implementation is immutable, thread-safe and {@code Serializable}
303
* providing that the base clock is.
304
*
305
* @param baseClock the base clock to base the ticking clock on, not null
306
* @param tickDuration the duration of each visible tick, not negative, not null
307
* @return a clock that ticks in whole units of the duration, not null
308
* @throws IllegalArgumentException if the duration is negative, or has a
309
* part smaller than a whole millisecond such that the whole duration is not
310
* divisible into one second
311
* @throws ArithmeticException if the duration is too large to be represented as nanos
312
*/
313
public static Clock tick(Clock baseClock, Duration tickDuration) {
314
Objects.requireNonNull(baseClock, "baseClock");
315
Objects.requireNonNull(tickDuration, "tickDuration");
316
if (tickDuration.isNegative()) {
317
throw new IllegalArgumentException("Tick duration must not be negative");
318
}
319
long tickNanos = tickDuration.toNanos();
320
if (tickNanos % 1000_000 == 0) {
321
// ok, no fraction of millisecond
322
} else if (1000_000_000 % tickNanos == 0) {
323
// ok, divides into one second without remainder
324
} else {
325
throw new IllegalArgumentException("Invalid tick duration");
326
}
327
if (tickNanos <= 1) {
328
return baseClock;
329
}
330
return new TickClock(baseClock, tickNanos);
331
}
332
333
//-----------------------------------------------------------------------
334
/**
335
* Obtains a clock that always returns the same instant.
336
* <p>
337
* This clock simply returns the specified instant.
338
* As such, it is not a clock in the conventional sense.
339
* The main use case for this is in testing, where the fixed clock ensures
340
* tests are not dependent on the current clock.
341
* <p>
342
* The returned implementation is immutable, thread-safe and {@code Serializable}.
343
*
344
* @param fixedInstant the instant to use as the clock, not null
345
* @param zone the time-zone to use to convert the instant to date-time, not null
346
* @return a clock that always returns the same instant, not null
347
*/
348
public static Clock fixed(Instant fixedInstant, ZoneId zone) {
349
Objects.requireNonNull(fixedInstant, "fixedInstant");
350
Objects.requireNonNull(zone, "zone");
351
return new FixedClock(fixedInstant, zone);
352
}
353
354
//-------------------------------------------------------------------------
355
/**
356
* Obtains a clock that returns instants from the specified clock with the
357
* specified duration added
358
* <p>
359
* This clock wraps another clock, returning instants that are later by the
360
* specified duration. If the duration is negative, the instants will be
361
* earlier than the current date and time.
362
* The main use case for this is to simulate running in the future or in the past.
363
* <p>
364
* A duration of zero would have no offsetting effect.
365
* Passing zero will return the underlying clock.
366
* <p>
367
* The returned implementation is immutable, thread-safe and {@code Serializable}
368
* providing that the base clock is.
369
*
370
* @param baseClock the base clock to add the duration to, not null
371
* @param offsetDuration the duration to add, not null
372
* @return a clock based on the base clock with the duration added, not null
373
*/
374
public static Clock offset(Clock baseClock, Duration offsetDuration) {
375
Objects.requireNonNull(baseClock, "baseClock");
376
Objects.requireNonNull(offsetDuration, "offsetDuration");
377
if (offsetDuration.equals(Duration.ZERO)) {
378
return baseClock;
379
}
380
return new OffsetClock(baseClock, offsetDuration);
381
}
382
383
//-----------------------------------------------------------------------
384
/**
385
* Constructor accessible by subclasses.
386
*/
387
protected Clock() {
388
}
389
390
//-----------------------------------------------------------------------
391
/**
392
* Gets the time-zone being used to create dates and times.
393
* <p>
394
* A clock will typically obtain the current instant and then convert that
395
* to a date or time using a time-zone. This method returns the time-zone used.
396
*
397
* @return the time-zone being used to interpret instants, not null
398
*/
399
public abstract ZoneId getZone();
400
401
/**
402
* Returns a copy of this clock with a different time-zone.
403
* <p>
404
* A clock will typically obtain the current instant and then convert that
405
* to a date or time using a time-zone. This method returns a clock with
406
* similar properties but using a different time-zone.
407
*
408
* @param zone the time-zone to change to, not null
409
* @return a clock based on this clock with the specified time-zone, not null
410
*/
411
public abstract Clock withZone(ZoneId zone);
412
413
//-------------------------------------------------------------------------
414
/**
415
* Gets the current millisecond instant of the clock.
416
* <p>
417
* This returns the millisecond-based instant, measured from 1970-01-01T00:00Z (UTC).
418
* This is equivalent to the definition of {@link System#currentTimeMillis()}.
419
* <p>
420
* Most applications should avoid this method and use {@link Instant} to represent
421
* an instant on the time-line rather than a raw millisecond value.
422
* This method is provided to allow the use of the clock in high performance use cases
423
* where the creation of an object would be unacceptable.
424
* <p>
425
* The default implementation currently calls {@link #instant}.
426
*
427
* @return the current millisecond instant from this clock, measured from
428
* the Java epoch of 1970-01-01T00:00Z (UTC), not null
429
* @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations
430
*/
431
public long millis() {
432
return instant().toEpochMilli();
433
}
434
435
//-----------------------------------------------------------------------
436
/**
437
* Gets the current instant of the clock.
438
* <p>
439
* This returns an instant representing the current instant as defined by the clock.
440
*
441
* @return the current instant from this clock, not null
442
* @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations
443
*/
444
public abstract Instant instant();
445
446
//-----------------------------------------------------------------------
447
/**
448
* Checks if this clock is equal to another clock.
449
* <p>
450
* Clocks should override this method to compare equals based on
451
* their state and to meet the contract of {@link Object#equals}.
452
* If not overridden, the behavior is defined by {@link Object#equals}
453
*
454
* @param obj the object to check, null returns false
455
* @return true if this is equal to the other clock
456
*/
457
@Override
458
public boolean equals(Object obj) {
459
return super.equals(obj);
460
}
461
462
/**
463
* A hash code for this clock.
464
* <p>
465
* Clocks should override this method based on
466
* their state and to meet the contract of {@link Object#hashCode}.
467
* If not overridden, the behavior is defined by {@link Object#hashCode}
468
*
469
* @return a suitable hash code
470
*/
471
@Override
472
public int hashCode() {
473
return super.hashCode();
474
}
475
476
//-----------------------------------------------------------------------
477
/**
478
* Implementation of a clock that always returns the latest time from
479
* {@link System#currentTimeMillis()}.
480
*/
481
static final class SystemClock extends Clock implements Serializable {
482
@java.io.Serial
483
private static final long serialVersionUID = 6740630888130243051L;
484
private static final long OFFSET_SEED =
485
System.currentTimeMillis()/1000 - 1024; // initial offest
486
static final SystemClock UTC = new SystemClock(ZoneOffset.UTC);
487
488
private final ZoneId zone;
489
// We don't actually need a volatile here.
490
// We don't care if offset is set or read concurrently by multiple
491
// threads - we just need a value which is 'recent enough' - in other
492
// words something that has been updated at least once in the last
493
// 2^32 secs (~136 years). And even if we by chance see an invalid
494
// offset, the worst that can happen is that we will get a -1 value
495
// from getNanoTimeAdjustment, forcing us to update the offset
496
// once again.
497
private transient long offset;
498
499
SystemClock(ZoneId zone) {
500
this.zone = zone;
501
this.offset = OFFSET_SEED;
502
}
503
@Override
504
public ZoneId getZone() {
505
return zone;
506
}
507
@Override
508
public Clock withZone(ZoneId zone) {
509
if (zone.equals(this.zone)) { // intentional NPE
510
return this;
511
}
512
return new SystemClock(zone);
513
}
514
@Override
515
public long millis() {
516
// System.currentTimeMillis() and VM.getNanoTimeAdjustment(offset)
517
// use the same time source - System.currentTimeMillis() simply
518
// limits the resolution to milliseconds.
519
// So we take the faster path and call System.currentTimeMillis()
520
// directly - in order to avoid the performance penalty of
521
// VM.getNanoTimeAdjustment(offset) which is less efficient.
522
return System.currentTimeMillis();
523
}
524
@Override
525
public Instant instant() {
526
// Take a local copy of offset. offset can be updated concurrently
527
// by other threads (even if we haven't made it volatile) so we will
528
// work with a local copy.
529
long localOffset = offset;
530
long adjustment = VM.getNanoTimeAdjustment(localOffset);
531
532
if (adjustment == -1) {
533
// -1 is a sentinel value returned by VM.getNanoTimeAdjustment
534
// when the offset it is given is too far off the current UTC
535
// time. In principle, this should not happen unless the
536
// JVM has run for more than ~136 years (not likely) or
537
// someone is fiddling with the system time, or the offset is
538
// by chance at 1ns in the future (very unlikely).
539
// We can easily recover from all these conditions by bringing
540
// back the offset in range and retry.
541
542
// bring back the offset in range. We use -1024 to make
543
// it more unlikely to hit the 1ns in the future condition.
544
localOffset = System.currentTimeMillis()/1000 - 1024;
545
546
// retry
547
adjustment = VM.getNanoTimeAdjustment(localOffset);
548
549
if (adjustment == -1) {
550
// Should not happen: we just recomputed a new offset.
551
// It should have fixed the issue.
552
throw new InternalError("Offset " + localOffset + " is not in range");
553
} else {
554
// OK - recovery succeeded. Update the offset for the
555
// next call...
556
offset = localOffset;
557
}
558
}
559
return Instant.ofEpochSecond(localOffset, adjustment);
560
}
561
@Override
562
public boolean equals(Object obj) {
563
if (obj instanceof SystemClock) {
564
return zone.equals(((SystemClock) obj).zone);
565
}
566
return false;
567
}
568
@Override
569
public int hashCode() {
570
return zone.hashCode() + 1;
571
}
572
@Override
573
public String toString() {
574
return "SystemClock[" + zone + "]";
575
}
576
@java.io.Serial
577
private void readObject(ObjectInputStream is)
578
throws IOException, ClassNotFoundException {
579
// ensure that offset is initialized
580
is.defaultReadObject();
581
offset = OFFSET_SEED;
582
}
583
}
584
585
//-----------------------------------------------------------------------
586
/**
587
* Implementation of a clock that always returns the same instant.
588
* This is typically used for testing.
589
*/
590
static final class FixedClock extends Clock implements Serializable {
591
@java.io.Serial
592
private static final long serialVersionUID = 7430389292664866958L;
593
private final Instant instant;
594
private final ZoneId zone;
595
596
FixedClock(Instant fixedInstant, ZoneId zone) {
597
this.instant = fixedInstant;
598
this.zone = zone;
599
}
600
@Override
601
public ZoneId getZone() {
602
return zone;
603
}
604
@Override
605
public Clock withZone(ZoneId zone) {
606
if (zone.equals(this.zone)) { // intentional NPE
607
return this;
608
}
609
return new FixedClock(instant, zone);
610
}
611
@Override
612
public long millis() {
613
return instant.toEpochMilli();
614
}
615
@Override
616
public Instant instant() {
617
return instant;
618
}
619
@Override
620
public boolean equals(Object obj) {
621
return obj instanceof FixedClock other
622
&& instant.equals(other.instant)
623
&& zone.equals(other.zone);
624
}
625
@Override
626
public int hashCode() {
627
return instant.hashCode() ^ zone.hashCode();
628
}
629
@Override
630
public String toString() {
631
return "FixedClock[" + instant + "," + zone + "]";
632
}
633
}
634
635
//-----------------------------------------------------------------------
636
/**
637
* Implementation of a clock that adds an offset to an underlying clock.
638
*/
639
static final class OffsetClock extends Clock implements Serializable {
640
@java.io.Serial
641
private static final long serialVersionUID = 2007484719125426256L;
642
@SuppressWarnings("serial") // Not statically typed as Serializable
643
private final Clock baseClock;
644
private final Duration offset;
645
646
OffsetClock(Clock baseClock, Duration offset) {
647
this.baseClock = baseClock;
648
this.offset = offset;
649
}
650
@Override
651
public ZoneId getZone() {
652
return baseClock.getZone();
653
}
654
@Override
655
public Clock withZone(ZoneId zone) {
656
if (zone.equals(baseClock.getZone())) { // intentional NPE
657
return this;
658
}
659
return new OffsetClock(baseClock.withZone(zone), offset);
660
}
661
@Override
662
public long millis() {
663
return Math.addExact(baseClock.millis(), offset.toMillis());
664
}
665
@Override
666
public Instant instant() {
667
return baseClock.instant().plus(offset);
668
}
669
@Override
670
public boolean equals(Object obj) {
671
return obj instanceof OffsetClock other
672
&& baseClock.equals(other.baseClock)
673
&& offset.equals(other.offset);
674
}
675
@Override
676
public int hashCode() {
677
return baseClock.hashCode() ^ offset.hashCode();
678
}
679
@Override
680
public String toString() {
681
return "OffsetClock[" + baseClock + "," + offset + "]";
682
}
683
}
684
685
//-----------------------------------------------------------------------
686
/**
687
* Implementation of a clock that adds an offset to an underlying clock.
688
*/
689
static final class TickClock extends Clock implements Serializable {
690
@java.io.Serial
691
private static final long serialVersionUID = 6504659149906368850L;
692
@SuppressWarnings("serial") // Not statically typed as Serializable
693
private final Clock baseClock;
694
private final long tickNanos;
695
696
TickClock(Clock baseClock, long tickNanos) {
697
this.baseClock = baseClock;
698
this.tickNanos = tickNanos;
699
}
700
@Override
701
public ZoneId getZone() {
702
return baseClock.getZone();
703
}
704
@Override
705
public Clock withZone(ZoneId zone) {
706
if (zone.equals(baseClock.getZone())) { // intentional NPE
707
return this;
708
}
709
return new TickClock(baseClock.withZone(zone), tickNanos);
710
}
711
@Override
712
public long millis() {
713
long millis = baseClock.millis();
714
return millis - Math.floorMod(millis, tickNanos / 1000_000L);
715
}
716
@Override
717
public Instant instant() {
718
if ((tickNanos % 1000_000) == 0) {
719
long millis = baseClock.millis();
720
return Instant.ofEpochMilli(millis - Math.floorMod(millis, tickNanos / 1000_000L));
721
}
722
Instant instant = baseClock.instant();
723
long nanos = instant.getNano();
724
long adjust = Math.floorMod(nanos, tickNanos);
725
return instant.minusNanos(adjust);
726
}
727
@Override
728
public boolean equals(Object obj) {
729
return (obj instanceof TickClock other)
730
&& tickNanos == other.tickNanos
731
&& baseClock.equals(other.baseClock);
732
}
733
@Override
734
public int hashCode() {
735
return baseClock.hashCode() ^ ((int) (tickNanos ^ (tickNanos >>> 32)));
736
}
737
@Override
738
public String toString() {
739
return "TickClock[" + baseClock + "," + Duration.ofNanos(tickNanos) + "]";
740
}
741
}
742
743
}
744
745