JAVA8之 日期时间时区之 Clock和Instant 笔记

文章目录


前言

据说爱因斯坦通过研究时间发现了E=MC2
向爱坦大神学习,本人希望通过研究时间能讨口饭吃
也向编程大神们学习,希望能从他们的编程思路中获得启发


Clock

源码分析 来自(OpenJDK15)

类说明翻译

时钟提供time-zone访问instant,date和time。

此类的实例用于查找当前的instant,可以使用存储的时区对其进行解释以查找当前日期和时间。因此,可以使用Clock代替System.currentTimeMillis()和TimeZone.getDefault() 。

时钟的使用是可选的。所有关键日期时间类还具有now()工厂方法,该方法在默认时区使用系统时钟。此抽象的主要目的是允许在需要时插入备用时钟。应用程序使用对象而不是静态方法来获取当前时间。这样可以简化测试。

应用程序的最佳实践是将Clock传递到需要当前时刻的任何方法中。依赖项注入框架是实现此目标的一种方法:
 *  public class MyBean {
 *    private Clock clock;  // dependency inject
 *    ...
 *    public void process(LocalDate eventDate) {
 *      if (eventDate.isBefore(LocalDate.now(clock)) {
 *        ...
 *      }
 *    }
 *  }
 
这种方法允许在测试过程中使用备用时钟,例如固定时钟或偏移时钟。
系统工厂方法基于最佳可用系统时钟提供时钟。该系统时钟可以使用System.currentTimeMillis(),或者使用更高分辨率的时钟(如果有)。

从java1.8开始引入

必须谨慎实施此抽象类,以确保其他类正确运行。所有可实例化的实现都必须是最终的,不可变的且是线程安全的。
定义了主要方法以允许抛出异常。在正常使用中,不会抛出异常,但是一种可能的实现方式是从网络中的中央时间服务器获取时间。显然,在这种情况下,查找可能会失败,因此允许该方法引发异常。

从“时钟”返回的瞬间按忽略“ leap秒”的时间范围工作,如“即时”中所述。如果该实现包装了提供leap秒信息的源,则应使用一种机制来“平滑” the秒。JavaTime-Scale强制使用UTC-SLS,但是时钟实现可能会选择它们在时间上的准确性。只要它们记录了工作原理,就可以进行扩展。因此不需要实际执行UTC-SLS摆率就可以实现,也不必知道leap秒。

实现应尽可能实现Serializable,并且必须记录它们是否支持序列化。
注意:此处提供的时钟实现基于与System.currentTimeMillis()相同的基础时钟,但是精度可能会比毫秒(如果可用)还好。但是,几乎不能保证底层时钟的准确性。需要更精确时钟的应用程序必须使用其他外部时钟(例如,NTP服务器)自己实现此抽象类。 

Clock是一个抽象类

public abstract class Clock

Clock有4个实现类在同文件下

分别是
SystemClock FixedClock OffsetClock TickClock
可以发现它们的成员变量并不相同, 从成员变量可推断它们各自的用途
Clock的成员变量都是final不可变的

SystemClock 系统时间+系统时区
    /**
     * Implementation of a clock that always returns the latest time from
     * {@link System#currentTimeMillis()}.
     */
    static final class SystemClock extends Clock implements Serializable {

SystemClock 成员变量

        private static final long OFFSET_SEED =
                System.currentTimeMillis()/1000 - 1024; // initial offest
        static final SystemClock UTC = new SystemClock(ZoneOffset.UTC);

        private final ZoneId zone;
        // We don't actually need a volatile here.
        // We don't care if offset is set or read concurrently by multiple
        // threads - we just need a value which is 'recent enough' - in other
        // words something that has been updated at least once in the last
        // 2^32 secs (~136 years). And even if we by chance see an invalid
        // offset, the worst that can happen is that we will get a -1 value
        // from getNanoTimeAdjustment, forcing us to update the offset
        // once again.
        private transient long offset;

可看出SystemClock就是系统UTC+系统时区

FixedClock 时刻+时区
    /**
     * Implementation of a clock that always returns the same instant.
     * This is typically used for testing.
     */
    static final class FixedClock extends Clock implements Serializable {

FixedClock成员变量

        private final Instant instant;
        private final ZoneId zone;

可看出FixedClock就是Instant+ZoneId(UTC时刻+时区)

OffsetClock 表示一段时间差 用Duration包装
    /**
     * Implementation of a clock that adds an offset to an underlying clock.
     */
    static final class OffsetClock extends Clock implements Serializable {

OffsetClock成员变量

        private final Clock baseClock;
        private final Duration offset;
TickClock 表示一段时间差 用纳秒
    /**
     * Implementation of a clock that adds an offset to an underlying clock.
     */
    static final class TickClock extends Clock implements Serializable {

TickClock成员变量

        private final Clock baseClock;
        private final long tickNanos;

Clock的4个主要专属方法

从getZone()和instant()方法可以得知,Clock同时具有时间和时区的属性,虽然未必是成员变量

ZoneId getZone()
    /**
     * Gets the time-zone being used to create dates and times.
     * <p>
     * A clock will typically obtain the current instant and then convert that
     * to a date or time using a time-zone. This method returns the time-zone used.
     *
     * @return the time-zone being used to interpret instants, not null
     */
    public abstract ZoneId getZone();
Clock withZone(ZoneId zone)
    /**
     * Returns a copy of this clock with a different time-zone.
     * <p>
     * A clock will typically obtain the current instant and then convert that
     * to a date or time using a time-zone. This method returns a clock with
     * similar properties but using a different time-zone.
     *
     * @param zone  the time-zone to change to, not null
     * @return a clock based on this clock with the specified time-zone, not null
     */
    public abstract Clock withZone(ZoneId zone);
long millis()
    public long millis() {
        return instant().toEpochMilli();
    }
Instant instant()
    /**
     * Gets the current instant of the clock.
     * <p>
     * This returns an instant representing the current instant as defined by the clock.
     *
     * @return the current instant from this clock, not null
     * @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations
     */
    public abstract Instant instant();

Instant

源码分析 来自(OpenJDK15)

类说明翻译

时间线上的瞬时点。

此类在时间轴上为单个瞬时点建模,可用于记录应用程序中的事件时间戳。

瞬时范围需要存储大于整数的数字,为实现此目的,该类存储了一个long表示纪元秒和一个int代表纳秒数,该整数始终在0到999,999,999之间。 -秒是从1970-01-01T00:00:00Z的标准Java纪元开始测量的,该纪元之后的时刻具有正值,而较早的时刻具有负值。在时间轴上比一个较小的值。

时间尺度

太阳日的长短是人类测量时间的标准方法。传统上,太阳日的长短可细分为60小时的60分钟的24小时,即第二天的86400。

现代计时基于原子钟,该原子钟精确地定义了相对于铯原子跃迁第二的SI。 SI秒的长度被定义为非常接近一天的第86400个分数。

不幸的是,随着地球旋转,一天的长度会有所不同。此外,随着时间的推移,随着地球的变慢,一天的平均长度会变长,因此,2012年太阳日的长度略长于86400 SI给定日期的实际长度和地球变慢的量是无法预测的,只能通过测量来确定.UT1时标可以捕获准确的一天长度,但仅在一天完成后的某个时间可用。

UTC时间尺度是将UT1的所有额外秒数捆绑成整秒(称为leap秒)的一种标准方法,根据地球的自转变化可以添加或删除leap秒。允许一天有86399 SI秒或86401 SI秒,以使一天与太阳对齐。

现代UTC时标于1972年引入,引入了整个leap秒的概念.1958年至1972年之间,UTC的定义很复杂,次秒级的跳跃和变化都达到了概念秒的长度。截至2012年,正在讨论再次更改UTC的定义,并可能删除leap秒或引发其他更改。

考虑到上述精确计时的复杂性,此Java API定义了自己的时间标度,即Java时间标度。

Java时间刻度将每个日历日精确划分为86400个细分,称为秒。这些秒可能与SI秒不同。它与事实上的国际民用时标紧密匹配,其定义会不时变化。

Java Time-Scale对时间线的不同段有稍微不同的定义,每个定义都基于用作民用时间基础的国际共识时间标度。每当修改或替换国际商定的时标时,都必须为其定义Java Time-Scale的新闻片段。每个细分市场都必须满足以下要求:
Java时间标度应与基础国际民用时间标度紧密匹配;
•Java时间刻度应每天中午与国际民用时间刻度完全匹配;
•Java时标应与国际民用时标有精确定义的关系。
截至2013年,Java时间范围目前分为两个部分。
对于从1972-11-03到进一步通知的这段时间(下面将讨论确切的边界),共识的国际时间范围是UTC(无跳秒)。在此部分中,Java时间刻度与UTC-SLS相同,在没有a秒的日子中与UTC相同。在具有a秒的日子中,the秒平均分布在最后1000秒内一天的时间,每天保持精确的86400秒的外观。

对于1972-11-03之前的任意段,向后任意延伸,将共识国际时间标度定义为UT1,适用于时间,这等于本初子午线(格林威治)上的(平均)太阳时间。在这一部分中,Java Time-Scale与国际共识的时间尺度相同。这两个段之间的确切边界是UT1 = UTTC在1972-11-03T00:00和1972-11-04T12:00之间的时刻。

不需要使用JSR-310 API来实现Java时标,即可提供亚秒级精度或单调或平滑进行的任何时钟。因此,不需要实际执行UTC-SLS转换或以其他方式意识到秒的实现。但是,JSR-310确实要求实现必须记录它们在定义代表当前时刻的时钟时使用的方法。有关可用时钟的详细信息,请参见“时钟”。

Java时间刻度适用于所有日期时间类,其中包括Instant,LocalDate,LocalTime,OffsetDateTime,ZonedDateTime和Duration。

这是一个基于值的类; 在Instant实例上使用标识敏感的操作(包括引用相等性(==),标识哈希码或同步)可能会产生不可预测的结果,应避免使用equals方法进行比较。

从java1.8开始引入

此类是不可变的并且是线程安全的。

Instant是一个final class , 看到final class舒服啊, 不会有各种衍生体

public final class Instant
        implements Temporal, TemporalAdjuster, Comparable<Instant>, Serializable {

静态常量

三个静态最终实例
EPOCH 表示 1970-01-01T00:00:00Z (Z表示UTC)
    /**
     * Constant for the 1970-01-01T00:00:00Z epoch instant.
     */
    public static final Instant EPOCH = new Instant(0, 0);

可看到实例化方法new Instant(0, 0); Instant本身只保存seconds 和 nanos两个成员变量, 没有时区, 但代表UTC

MAX 和 MIN 表示最大值和最小值的实例
    /**
     * The minimum supported {@code Instant}, '-1000000000-01-01T00:00Z'.
     * This could be used by an application as a "far past" instant.
     * <p>
     * This is one year earlier than the minimum {@code LocalDateTime}.
     * This provides sufficient values to handle the range of {@code ZoneOffset}
     * which affect the instant in addition to the local date-time.
     * The value is also chosen such that the value of the year fits in
     * an {@code int}.
     */
    public static final Instant MIN = Instant.ofEpochSecond(MIN_SECOND, 0);
    /**
     * The maximum supported {@code Instant}, '1000000000-12-31T23:59:59.999999999Z'.
     * This could be used by an application as a "far future" instant.
     * <p>
     * This is one year later than the maximum {@code LocalDateTime}.
     * This provides sufficient values to handle the range of {@code ZoneOffset}
     * which affect the instant in addition to the local date-time.
     * The value is also chosen such that the value of the year fits in
     * an {@code int}.
     */
    public static final Instant MAX = Instant.ofEpochSecond(MAX_SECOND, 999_999_999);

可表示1970前后十亿年

秒范围正负范围 推断可轻松表示1970正负亿级年份
    /**
     * The minimum supported epoch second.
     */
    private static final long MIN_SECOND = -31557014167219200L;
    /**
     * The maximum supported epoch second.
     */
    private static final long MAX_SECOND = 31556889864403199L;

只有两个成员变量 seconds 和 nanos (并且是final的)

    /**
     * The number of seconds from the epoch of 1970-01-01T00:00:00Z.
     */
    private final long seconds;
    /**
     * The number of nanoseconds, later along the time-line, from the seconds field.
     * This is always positive, and never exceeds 999,999,999.
     */
    private final int nanos;

可以看出,Instant用秒和纳秒确定时刻, 区分精度为纳秒 , 用final修饰表示不可修改, 这也是它线程安全的原因

实例化过程分析

最终都会调用 private Instant(long , int )方法

    private Instant(long epochSecond, int nanos) {
        super();
        this.seconds = epochSecond;
        this.nanos = nanos;
    }

Instant.now() 后 toString简单演示说明

系统时间为我国时区2021-04-08T01:29:22 执行下面代码👇

System.out.println(Instant.now());

结果: 2021-04-07T17:29:22.573585600Z
说明Instant的toString方法返回UTC时间 结尾Z表示UTC

Instant.now() 的过程

    public static Instant now() {
        return Clock.systemUTC().instant();
    }

调用了 SystemClock 的 instant() 方法

        @Override
        public Instant instant() {
            // Take a local copy of offset. offset can be updated concurrently
            // by other threads (even if we haven't made it volatile) so we will
            // work with a local copy.
            long localOffset = offset;
            long adjustment = VM.getNanoTimeAdjustment(localOffset);

            if (adjustment == -1) {
                // -1 is a sentinel value returned by VM.getNanoTimeAdjustment
                // when the offset it is given is too far off the current UTC
                // time. In principle, this should not happen unless the
                // JVM has run for more than ~136 years (not likely) or
                // someone is fiddling with the system time, or the offset is
                // by chance at 1ns in the future (very unlikely).
                // We can easily recover from all these conditions by bringing
                // back the offset in range and retry.

                // bring back the offset in range. We use -1024 to make
                // it more unlikely to hit the 1ns in the future condition.
                localOffset = System.currentTimeMillis()/1000 - 1024;

                // retry
                adjustment = VM.getNanoTimeAdjustment(localOffset);

                if (adjustment == -1) {
                    // Should not happen: we just recomputed a new offset.
                    // It should have fixed the issue.
                    throw new InternalError("Offset " + localOffset + " is not in range");
                } else {
                    // OK - recovery succeeded. Update the offset for the
                    // next call...
                    offset = localOffset;
                }
            }
            return Instant.ofEpochSecond(localOffset, adjustment);
        }

调用了 Instant 的 ofEpochSecond(long epochSecond, long nanoAdjustment) 静态方法

    public static Instant ofEpochSecond(long epochSecond, long nanoAdjustment) {
        long secs = Math.addExact(epochSecond, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND));
        int nos = (int)Math.floorMod(nanoAdjustment, NANOS_PER_SECOND);
        return create(secs, nos);
    }

调用了 Instant 的 create(long seconds, int nanoOfSecond) 私有方法

    private static Instant create(long seconds, int nanoOfSecond) {
        if ((seconds | nanoOfSecond) == 0) {
            return EPOCH;
        }
        if (seconds < MIN_SECOND || seconds > MAX_SECOND) {
            throw new DateTimeException("Instant exceeds minimum or maximum instant");
        }
        return new Instant(seconds, nanoOfSecond);
    }

调用了 Instant 的 private Instant(long epochSecond, int nanos) 方法

now(Clock clock)的过程

    public static Instant now(Clock clock) {
        Objects.requireNonNull(clock, "clock");
        return clock.instant();
    }

通过 Clock 的 instant()方法获得Instant实例 , 具体怎么获得, 要看是什么Clock , 然后都是Instant自己的方法 , 最终调用 Instant 的 private Instant(long epochSecond, int nanos) 方法
now(Clock clock)是以当前时间为基础,指定时区或时差偏移,获得Instant实例

parse(final CharSequence text) 解析字符串的过程

    /**
     * Obtains an instance of {@code Instant} from a text string such as
     * {@code 2007-12-03T10:15:30.00Z}.
     * <p>
     * The string must represent a valid instant in UTC and is parsed using
     * {@link DateTimeFormatter#ISO_INSTANT}.
     *
     * @param text  the text to parse, not null
     * @return the parsed instant, not null
     * @throws DateTimeParseException if the text cannot be parsed
     */
    public static Instant parse(final CharSequence text) {
        return DateTimeFormatter.ISO_INSTANT.parse(text, Instant::from);
    }

使用了 DateTimeFormatter 来进行解析
过程太复杂了…
但看到 DateTimeFormatter 有个现成实例 ISO_INSTANT

主要公有成员方法

plus

私有plus核心方法:

    private Instant plus(long secondsToAdd, long nanosToAdd) {
        if ((secondsToAdd | nanosToAdd) == 0) {
            return this;
        }
        long epochSec = Math.addExact(seconds, secondsToAdd);
        epochSec = Math.addExact(epochSec, nanosToAdd / NANOS_PER_SECOND);
        nanosToAdd = nanosToAdd % NANOS_PER_SECOND;
        long nanoAdjustment = nanos + nanosToAdd;  // safe int+NANOS_PER_SECOND
        return ofEpochSecond(epochSec, nanoAdjustment);
    }

👆其它plus最后都会调用这个方法, 但凡有变动都会生成新实例, 实现线程安全

Instant plus(TemporalAmount amountToAdd)
    @Override
    public Instant plus(TemporalAmount amountToAdd) {
        return (Instant) amountToAdd.addTo(this);
    }

👆加 @Override 是因为这个方法扩展自 Temporal 的默认方法

Instant plus(long amountToAdd, TemporalUnit unit)
    @Override
    public Instant plus(long amountToAdd, TemporalUnit unit) {
        if (unit instanceof ChronoUnit) {
            switch ((ChronoUnit) unit) {
                case NANOS: return plusNanos(amountToAdd);
                case MICROS: return plus(amountToAdd / 1000_000, (amountToAdd % 1000_000) * 1000);
                case MILLIS: return plusMillis(amountToAdd);
                case SECONDS: return plusSeconds(amountToAdd);
                case MINUTES: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_MINUTE));
                case HOURS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_HOUR));
                case HALF_DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY / 2));
                case DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY));
            }
            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
        }
        return unit.addTo(this, amountToAdd);
    }
Instant plusSeconds(long secondsToAdd) 加秒
    public Instant plusSeconds(long secondsToAdd) {
        return plus(secondsToAdd, 0);
    }
Instant plusMillis(long millisToAdd) 加毫秒
    public Instant plusMillis(long millisToAdd) {
        return plus(millisToAdd / 1000, (millisToAdd % 1000) * 1000_000);
    }

👆毫秒被转换为秒和纳秒

Instant plusNanos(long nanosToAdd) 加纳秒
    public Instant plusNanos(long nanosToAdd) {
        return plus(0, nanosToAdd);
    }

minus

minus(数值)方法基本都是取负调用plus方法 但有判断过程

Instant minus(TemporalAmount amountToSubtract)
    @Override
    public Instant minus(TemporalAmount amountToSubtract) {
        return (Instant) amountToSubtract.subtractFrom(this);
    }
Instant minus(long amountToSubtract, TemporalUnit unit)
    @Override
    public Instant minus(long amountToSubtract, TemporalUnit unit) {
        return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
    }
Instant minusSeconds(long secondsToSubtract) 减秒
    public Instant minusSeconds(long secondsToSubtract) {
        if (secondsToSubtract == Long.MIN_VALUE) {
            return plusSeconds(Long.MAX_VALUE).plusSeconds(1);
        }
        return plusSeconds(-secondsToSubtract);
    }
Instant minusMillis(long millisToSubtract) 减毫秒
    public Instant minusMillis(long millisToSubtract) {
        if (millisToSubtract == Long.MIN_VALUE) {
            return plusMillis(Long.MAX_VALUE).plusMillis(1);
        }
        return plusMillis(-millisToSubtract);
    }
Instant minusNanos(long nanosToSubtract) 减纳秒
    public Instant minusNanos(long nanosToSubtract) {
        if (nanosToSubtract == Long.MIN_VALUE) {
            return plusNanos(Long.MAX_VALUE).plusNanos(1);
        }
        return plusNanos(-nanosToSubtract);
    }

with

Instant with(TemporalAdjuster adjuster)
    @Override
    public Instant with(TemporalAdjuster adjuster) {
        return (Instant) adjuster.adjustInto(this);
    }
Instant with(TemporalField field, long newValue)
    @Override
    public Instant with(TemporalField field, long newValue) {
        if (field instanceof ChronoField) {
            ChronoField f = (ChronoField) field;
            f.checkValidValue(newValue);
            switch (f) {
                case MILLI_OF_SECOND: {
                    int nval = (int) newValue * 1000_000;
                    return (nval != nanos ? create(seconds, nval) : this);
                }
                case MICRO_OF_SECOND: {
                    int nval = (int) newValue * 1000;
                    return (nval != nanos ? create(seconds, nval) : this);
                }
                case NANO_OF_SECOND: return (newValue != nanos ? create(seconds, (int) newValue) : this);
                case INSTANT_SECONDS: return (newValue != seconds ? create(newValue, nanos) : this);
            }
            throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
        }
        return field.adjustInto(this, newValue);
    }

get

getEpochSecond() 返回19700101到现在的秒数
    /**
     * Gets the number of seconds from the Java epoch of 1970-01-01T00:00:00Z.
     * <p>
     * The epoch second count is a simple incrementing count of seconds where
     * second 0 is 1970-01-01T00:00:00Z.
     * The nanosecond part is returned by {@link #getNano}.
     *
     * @return the seconds from the epoch of 1970-01-01T00:00:00Z
     */
    public long getEpochSecond() {
        return seconds;
    }
getNano() 返回纳秒数 (单独使用是没有基点的)
    /**
     * Gets the number of nanoseconds, later along the time-line, from the start
     * of the second.
     * <p>
     * The nanosecond-of-second value measures the total number of nanoseconds from
     * the second returned by {@link #getEpochSecond}.
     *
     * @return the nanoseconds within the second, always positive, never exceeds 999,999,999
     */
    public int getNano() {
        return nanos;
    }

toEpochMilli() 返回1970年1月1日到现在的毫秒数

    /**
     * Converts this instant to the number of milliseconds from the epoch
     * of 1970-01-01T00:00:00Z.
     * <p>
     * If this instant represents a point on the time-line too far in the future
     * or past to fit in a {@code long} milliseconds, then an exception is thrown.
     * <p>
     * If this instant has greater than millisecond precision, then the conversion
     * will drop any excess precision information as though the amount in nanoseconds
     * was subject to integer division by one million.
     *
     * @return the number of milliseconds since the epoch of 1970-01-01T00:00:00Z
     * @throws ArithmeticException if numeric overflow occurs
     */
    public long toEpochMilli() {
        if (seconds < 0 && nanos > 0) {
            long millis = Math.multiplyExact(seconds+1, 1000);
            long adjustment = nanos / 1000_000 - 1000;
            return Math.addExact(millis, adjustment);
        } else {
            long millis = Math.multiplyExact(seconds, 1000);
            return Math.addExact(millis, nanos / 1000_000);
        }
    }

比较 compareTo , isAfter , isBefore

int compareTo(Instant otherInstant)
compareTo
    @Override
    public int compareTo(Instant otherInstant) {
        int cmp = Long.compare(seconds, otherInstant.seconds);
        if (cmp != 0) {
            return cmp;
        }
        return nanos - otherInstant.nanos;
    }

👆重写Object的方法 , 先比较秒, 比不出则再比较纳秒
可以看到isAfter和isBefore都是调用compareTo

isAfter
    public boolean isAfter(Instant otherInstant) {
        return compareTo(otherInstant) > 0;
    }
isBefore
    public boolean isBefore(Instant otherInstant) {
        return compareTo(otherInstant) < 0;
    }

until 方法返回long数值时间差 {纳秒,微秒,毫秒,秒,分,时,半天,天}可以设定

    /**
     * Calculates the amount of time until another instant in terms of the specified unit.
     * <p>
     * This calculates the amount of time between two {@code Instant}
     * objects in terms of a single {@code TemporalUnit}.
     * The start and end points are {@code this} and the specified instant.
     * The result will be negative if the end is before the start.
     * The calculation returns a whole number, representing the number of
     * complete units between the two instants.
     * The {@code Temporal} passed to this method is converted to a
     * {@code Instant} using {@link #from(TemporalAccessor)}.
     * For example, the amount in seconds between two dates can be calculated
     * using {@code startInstant.until(endInstant, SECONDS)}.
     * <p>
     * There are two equivalent ways of using this method.
     * The first is to invoke this method.
     * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
     * <pre>
     *   // these two lines are equivalent
     *   amount = start.until(end, SECONDS);
     *   amount = SECONDS.between(start, end);
     * </pre>
     * The choice should be made based on which makes the code more readable.
     * <p>
     * The calculation is implemented in this method for {@link ChronoUnit}.
     * The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
     * {@code MINUTES}, {@code HOURS}, {@code HALF_DAYS} and {@code DAYS}
     * are supported. Other {@code ChronoUnit} values will throw an exception.
     * <p>
     * If the unit is not a {@code ChronoUnit}, then the result of this method
     * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
     * passing {@code this} as the first argument and the converted input temporal
     * as the second argument.
     * <p>
     * This instance is immutable and unaffected by this method call.
     *
     * @param endExclusive  the end date, exclusive, which is converted to an {@code Instant}, not null
     * @param unit  the unit to measure the amount in, not null
     * @return the amount of time between this instant and the end instant
     * @throws DateTimeException if the amount cannot be calculated, or the end
     *  temporal cannot be converted to an {@code Instant}
     * @throws UnsupportedTemporalTypeException if the unit is not supported
     * @throws ArithmeticException if numeric overflow occurs
     */
    @Override
    public long until(Temporal endExclusive, TemporalUnit unit) {
        Instant end = Instant.from(endExclusive);
        if (unit instanceof ChronoUnit) {
            ChronoUnit f = (ChronoUnit) unit;
            switch (f) {
                case NANOS: return nanosUntil(end);
                case MICROS: return nanosUntil(end) / 1000;
                case MILLIS: return Math.subtractExact(end.toEpochMilli(), toEpochMilli());
                case SECONDS: return secondsUntil(end);
                case MINUTES: return secondsUntil(end) / SECONDS_PER_MINUTE;
                case HOURS: return secondsUntil(end) / SECONDS_PER_HOUR;
                case HALF_DAYS: return secondsUntil(end) / (12 * SECONDS_PER_HOUR);
                case DAYS: return secondsUntil(end) / (SECONDS_PER_DAY);
            }
            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit);
        }
        return unit.between(this, end);
    }

总结

看出Clock和Instant的关系为:
  • Clock可包含Instant和ZoneId
  • Instant的某些实例化过程使用了Clock
  • Instant.now(Clock clock)是以当前时间为基础,指定时区或时差偏移,获得Instant实例
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kfepiza

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值