Java 8 time api 文档及部分源码阅读(2)

java.time.Clock

封装了一个时区和一个时刻规则。

A clock providing access to the current instant, date and time using a time-zone.

上面是文档中的说法,但我觉得更合适的说法,应该是获取一个指定规则下的时刻,而并不是简单的current instant。比如这么写

A clock providing access to it's current instant, date and time using a time-zone.

不同clock具备不同的规则,获取的时刻(instant)也就不同。

这个类相对比较简单。只能说对时间的处理实在是太不讲道理了,可为难这帮编写工具库的大佬们了。用力猜,都有哪些对时间的操作需求呢?又是调查,又是统计的,做出来的工具,有一些功能可以说很接地气了。

我们先来看Clock的实例方法,因为单一就Clock一个类的功能和实现方式,还是挺特殊的,也有一定的参考意义。

实例方法很少,就放一块儿了。

首先java.time.Clock是个抽象类,所以这些实例方法具体行为取决于具体实现。但大方向上的意思是差不多的。getZone()方法,就是用来获取指定的时区的;withZone(ZoneId),保持时刻规则不变,变换时区(ps:当然,它是返回一个copy);instant(),返回指定规则下的时刻;millis(),返回指定规则下时刻所对应的毫秒数。

这个抽象类提供了四个实现类,这四个实现类,都是以静态内部类的形式,写在了java.time.Clock类内部。

java.time.Clock抽象类提供了几个静态方法,用来分别获取这四个实现类的实例。

从名字上就能对应起来。fixed(Instant, ZoneId)返回的就是FixedClock的实例,offset(Clock, Duration)是OffsetClock,system*()是SystemClock,tick*()是TickClock。

我们先从简单的来,fixed(Instant, ZoneId)指定一个时区,指定一个固定的时刻(fixedInstant)。也就是不管什么时候,这个方法返回的clock实例,获取的时刻都是指定的时刻fixedInstant,不会变化。

从代码上来看,一目了然。

恩,至于这个东西的用处,文档上是这么说的。

The main use case for this is in testing, where the fixed clock ensures tests are not dependent on the current clock.

隐隐感觉蛋蛋有点疼,哦,不是,是精神有点恍惚,总感觉哪个时候就用上它了,指定一个不变的时刻,恩,挺好的,mark一下。

第二个是system*()系列的方法。有时候,代码比文字的可读性更高。所以直接看代码。

所以我们可以看到,在SystemClock中,时刻规则就是当前的系统时刻。有一句需要提一下,时间戳这一类的东西,是没有时区一说的,使用System.currentTimeMillis()获取的毫秒数,在哪个国家都是一样的,然后再根据不同的时区将毫秒数转换为具体的时间。

所以SystemClock相当于是,只有时区规则,没有设定时刻规则,采用的是系统时刻。

第三个和第四个OffsetClock和TickClock都允许基于某个clock(时刻规则,时区规则),再增加一个时刻规则。也就是一个clock可能具有多个时刻规则。OffsetClock的时刻规则就是在已有时刻规则下,为时刻再添加一个间隔为Duration的偏移量,偏移量可正可负。TickClock的时刻规则,是指定一个duration,然后只返回时间轴上,已经经过的,最近的一个,整duration的时刻。我们先举例说明一下前几句话是什么意思。

当前时间在截图的正上方,17:36,OffsetClock和TickClock的实例,我都采用了系统时刻作为已有时刻规则,系统默认时区为时区规则(Clock.systemDefaultZone())。分别打印了,向后偏移30分钟,和tick30分钟的时刻。17:36,已经经过的,最近的一个,整30分钟的时刻,就是17:30。

这两个功能,我相信撸过几年代码的人,一定会喜不自禁,MD,真特么接地气,我做的xx项目里,可不就有这样的时间需求嘛~!

让我们再用几个例子自我满足一下。

offset可正可负,可以基于已有的clock,再加一条时刻规则,构成一个新的clock。

OffsetClock的源码很清晰。

就是简单的二者相加。

TickClock的源码也比较清晰。

我们可以看到,实现的过程其实很简单。

millis()方法都移除了小于毫秒的部分。

然而,我对TickClock的一个做法,有未知的疑问。

  • 为什么tickNanos一定要能被1秒整除?

从TickClock的代码来看,即便不能被1秒整除,也是work的。但Clock对TickClock的构造过程中,却做了这种限制。

此外,我们其实一直还没有发现,Clock为什么要引入时区规则?

2019-05-06更新:今日再回头看Clock,发现Clock如它的名字一样,像个时钟。世界上每个地方,都处于同一个时刻(Instant),但因为时区(Zone)不同,展示的时钟也就不同。所以时区规则和时刻规则,本就是独立的。相同的时刻规则,在不同的时区,展示的时间不同,但时刻值是相同的。Clock内部提供了四种实现,充分想象了我们会遇到的对时钟的需求:指定某个时区(国家)的标准时刻;指定某个时区的某个时刻;在指定时钟的基础上,添加一些时间的偏移;在指定时钟的基础上,只展示固定时间间隔的时刻。

这些都留到后面继续发现吧。

小结一下:

java.time.Clock本身是抽象类,通过静态方法,获取内置的四种实现类。四种实现类已经较为通用,但仍然开发了自由实现Clock的口子。这种写法,虽然不太符合单一职责原则,Clock类既做了接口声明,又提供了工厂方法,还内置了四种实现类,但有效的减少了类的数量,最重要的是,四个实现类并不复杂,即便集中在一个Clock中,也仍然比较清晰,并且能很好的将相关类聚合起来,减少查阅过程中,类与类之间频繁的跳转。

OffsetClock和TickClock都是基于已有的clock,所以组合起来,可以实现更为丰富的时刻规则。

四种实现类的对比:

SystemClockOffsetClockFixedClockTickClock
时刻规则系统时刻在已有规则上添加偏移量时刻固定不变最近经过的整duration
时区规则可指定遵循已有规则可指定遵循已有规则
可组装性不可组装可组装不可组装可组装

转载于:https://juejin.im/post/5c78ae486fb9a049f362cbf8

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值