1/*
2 * Copyright (c) 2012, 2015, 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 */
62package java.time;
63
64import java.io.IOException;
65import java.io.ObjectInputStream;
66import static java.time.LocalTime.NANOS_PER_MINUTE;
67import static java.time.LocalTime.NANOS_PER_SECOND;
68import static java.time.LocalTime.NANOS_PER_MILLI;
69import java.io.Serializable;
70import java.util.Objects;
71import java.util.TimeZone;
72import 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 */
140public 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        private static final long serialVersionUID = 6740630888130243051L;
483        private static final long OFFSET_SEED =
484                System.currentTimeMillis()/1000 - 1024; // initial offest
485        static final SystemClock UTC = new SystemClock(ZoneOffset.UTC);
486
487        private final ZoneId zone;
488        // We don't actually need a volatile here.
489        // We don't care if offset is set or read concurrently by multiple
490        // threads - we just need a value which is 'recent enough' - in other
491        // words something that has been updated at least once in the last
492        // 2^32 secs (~136 years). And even if we by chance see an invalid
493        // offset, the worst that can happen is that we will get a -1 value
494        // from getNanoTimeAdjustment, forcing us to update the offset
495        // once again.
496        private transient long offset;
497
498        SystemClock(ZoneId zone) {
499            this.zone = zone;
500            this.offset = OFFSET_SEED;
501        }
502        @Override
503        public ZoneId getZone() {
504            return zone;
505        }
506        @Override
507        public Clock withZone(ZoneId zone) {
508            if (zone.equals(this.zone)) {  // intentional NPE
509                return this;
510            }
511            return new SystemClock(zone);
512        }
513        @Override
514        public long millis() {
515            // System.currentTimeMillis() and VM.getNanoTimeAdjustment(offset)
516            // use the same time source - System.currentTimeMillis() simply
517            // limits the resolution to milliseconds.
518            // So we take the faster path and call System.currentTimeMillis()
519            // directly - in order to avoid the performance penalty of
520            // VM.getNanoTimeAdjustment(offset) which is less efficient.
521            return System.currentTimeMillis();
522        }
523        @Override
524        public Instant instant() {
525            // Take a local copy of offset. offset can be updated concurrently
526            // by other threads (even if we haven't made it volatile) so we will
527            // work with a local copy.
528            long localOffset = offset;
529            long adjustment = VM.getNanoTimeAdjustment(localOffset);
530
531            if (adjustment == -1) {
532                // -1 is a sentinel value returned by VM.getNanoTimeAdjustment
533                // when the offset it is given is too far off the current UTC
534                // time. In principle, this should not happen unless the
535                // JVM has run for more than ~136 years (not likely) or
536                // someone is fiddling with the system time, or the offset is
537                // by chance at 1ns in the future (very unlikely).
538                // We can easily recover from all these conditions by bringing
539                // back the offset in range and retry.
540
541                // bring back the offset in range. We use -1024 to make
542                // it more unlikely to hit the 1ns in the future condition.
543                localOffset = System.currentTimeMillis()/1000 - 1024;
544
545                // retry
546                adjustment = VM.getNanoTimeAdjustment(localOffset);
547
548                if (adjustment == -1) {
549                    // Should not happen: we just recomputed a new offset.
550                    // It should have fixed the issue.
551                    throw new InternalError("Offset " + localOffset + " is not in range");
552                } else {
553                    // OK - recovery succeeded. Update the offset for the
554                    // next call...
555                    offset = localOffset;
556                }
557            }
558            return Instant.ofEpochSecond(localOffset, adjustment);
559        }
560        @Override
561        public boolean equals(Object obj) {
562            if (obj instanceof SystemClock) {
563                return zone.equals(((SystemClock) obj).zone);
564            }
565            return false;
566        }
567        @Override
568        public int hashCode() {
569            return zone.hashCode() + 1;
570        }
571        @Override
572        public String toString() {
573            return "SystemClock[" + zone + "]";
574        }
575        private void readObject(ObjectInputStream is)
576                throws IOException, ClassNotFoundException {
577            // ensure that offset is initialized
578            is.defaultReadObject();
579            offset = OFFSET_SEED;
580        }
581    }
582
583    //-----------------------------------------------------------------------
584    /**
585     * Implementation of a clock that always returns the same instant.
586     * This is typically used for testing.
587     */
588    static final class FixedClock extends Clock implements Serializable {
589       private static final long serialVersionUID = 7430389292664866958L;
590        private final Instant instant;
591        private final ZoneId zone;
592
593        FixedClock(Instant fixedInstant, ZoneId zone) {
594            this.instant = fixedInstant;
595            this.zone = zone;
596        }
597        @Override
598        public ZoneId getZone() {
599            return zone;
600        }
601        @Override
602        public Clock withZone(ZoneId zone) {
603            if (zone.equals(this.zone)) {  // intentional NPE
604                return this;
605            }
606            return new FixedClock(instant, zone);
607        }
608        @Override
609        public long millis() {
610            return instant.toEpochMilli();
611        }
612        @Override
613        public Instant instant() {
614            return instant;
615        }
616        @Override
617        public boolean equals(Object obj) {
618            if (obj instanceof FixedClock) {
619                FixedClock other = (FixedClock) obj;
620                return instant.equals(other.instant) && zone.equals(other.zone);
621            }
622            return false;
623        }
624        @Override
625        public int hashCode() {
626            return instant.hashCode() ^ zone.hashCode();
627        }
628        @Override
629        public String toString() {
630            return "FixedClock[" + instant + "," + zone + "]";
631        }
632    }
633
634    //-----------------------------------------------------------------------
635    /**
636     * Implementation of a clock that adds an offset to an underlying clock.
637     */
638    static final class OffsetClock extends Clock implements Serializable {
639       private static final long serialVersionUID = 2007484719125426256L;
640        private final Clock baseClock;
641        private final Duration offset;
642
643        OffsetClock(Clock baseClock, Duration offset) {
644            this.baseClock = baseClock;
645            this.offset = offset;
646        }
647        @Override
648        public ZoneId getZone() {
649            return baseClock.getZone();
650        }
651        @Override
652        public Clock withZone(ZoneId zone) {
653            if (zone.equals(baseClock.getZone())) {  // intentional NPE
654                return this;
655            }
656            return new OffsetClock(baseClock.withZone(zone), offset);
657        }
658        @Override
659        public long millis() {
660            return Math.addExact(baseClock.millis(), offset.toMillis());
661        }
662        @Override
663        public Instant instant() {
664            return baseClock.instant().plus(offset);
665        }
666        @Override
667        public boolean equals(Object obj) {
668            if (obj instanceof OffsetClock) {
669                OffsetClock other = (OffsetClock) obj;
670                return baseClock.equals(other.baseClock) && offset.equals(other.offset);
671            }
672            return false;
673        }
674        @Override
675        public int hashCode() {
676            return baseClock.hashCode() ^ offset.hashCode();
677        }
678        @Override
679        public String toString() {
680            return "OffsetClock[" + baseClock + "," + offset + "]";
681        }
682    }
683
684    //-----------------------------------------------------------------------
685    /**
686     * Implementation of a clock that adds an offset to an underlying clock.
687     */
688    static final class TickClock extends Clock implements Serializable {
689        private static final long serialVersionUID = 6504659149906368850L;
690        private final Clock baseClock;
691        private final long tickNanos;
692
693        TickClock(Clock baseClock, long tickNanos) {
694            this.baseClock = baseClock;
695            this.tickNanos = tickNanos;
696        }
697        @Override
698        public ZoneId getZone() {
699            return baseClock.getZone();
700        }
701        @Override
702        public Clock withZone(ZoneId zone) {
703            if (zone.equals(baseClock.getZone())) {  // intentional NPE
704                return this;
705            }
706            return new TickClock(baseClock.withZone(zone), tickNanos);
707        }
708        @Override
709        public long millis() {
710            long millis = baseClock.millis();
711            return millis - Math.floorMod(millis, tickNanos / 1000_000L);
712        }
713        @Override
714        public Instant instant() {
715            if ((tickNanos % 1000_000) == 0) {
716                long millis = baseClock.millis();
717                return Instant.ofEpochMilli(millis - Math.floorMod(millis, tickNanos / 1000_000L));
718            }
719            Instant instant = baseClock.instant();
720            long nanos = instant.getNano();
721            long adjust = Math.floorMod(nanos, tickNanos);
722            return instant.minusNanos(adjust);
723        }
724        @Override
725        public boolean equals(Object obj) {
726            if (obj instanceof TickClock) {
727                TickClock other = (TickClock) obj;
728                return baseClock.equals(other.baseClock) && tickNanos == other.tickNanos;
729            }
730            return false;
731        }
732        @Override
733        public int hashCode() {
734            return baseClock.hashCode() ^ ((int) (tickNanos ^ (tickNanos >>> 32)));
735        }
736        @Override
737        public String toString() {
738            return "TickClock[" + baseClock + "," + Duration.ofNanos(tickNanos) + "]";
739        }
740    }
741
742}
743