《Java核心技术 卷II》日期和时间API的时间线
日期和时间API
Java1.0的Date类过于简单,大部分被弃用。
Java1.1引入Calendar类,但没有处理诸如闰秒之类的问题。
Java 8引入java.time.API,修正过去缺陷。
时间线
1967年,铯133原子的特性推导出了秒的精确定义。之后由原子钟网络维护官方时间。
1972年开始,偶尔需要插入闰秒来修改时间。闰秒这个痛点,计算机通过临近闰秒之前让时间变慢或快。本地时间并不精确,需要与外部事件服务同步。
Java的Date和Time的API规范要求Java使用的时间尺度为:
- 每天86400秒
- 每天正午与官方时间精确匹配
- 在其他时间点上,以精确定义的方法与官方时间接近匹配。
Instant
表示时间线上的某个点,原点是1970年1月1号午夜开始,每天86400秒推进,精确到纳秒。可追溯10亿年(Instant.MIN),最大值是公元10 0000 0000年的12月31日(希望那时候还有你这个人的痕迹)。
Instant.now()
静态方法会给出当前时刻,可以用equals和compareTo方法来比较两个对象。
可以将Instant对象用作时间戳。
静态方法
Duration.between
得到两个时刻之间的时间差。
时间差可以通过 toNanos,toMillis,
getSeconds(特殊关注一下)
,toMinutes,toHours,toDays获得时间长度。
精确到纳秒级
当心上溢问题,long值可以存储300年纳秒数,需要Duration短于这个时间,可以直接转纳秒数。
更长的时间差,可以用long来存储秒数,int来存储纳秒数。
检查某个算法至少比另一个算法快10倍
Duration timeElapsed2 = Duration.between(start2,end2);
boolean overTenTimesFaster = timeElapsed1.multipliedBy(10).minus(timeElapsed2).isNegative();
也可直接使用:
boolean overTenTimesFaster = timeElapsed1.toNanos()*10 < timeElapsed2.toNanos();
注释:Instant和Duration都是不可修改的类,乘法之类的操作后,返回一个新的实例。
使用Instant和Duration类对两个算法计时
package 第6章时间API.timeline;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 时间线
*/
public class Timeline {
public static void main(String[] args) {
Instant start = Instant.now();
runAlgorithm();
Instant end = Instant.now();
Duration timeElapsed = Duration.between(start, end);
long millis = timeElapsed.toMillis();
System.out.printf("%d 毫秒数\n", millis);
Instant start2 = Instant.now();
runAlgorithm2();
Instant end2 = Instant.now();
Duration timeElapsed2 = Duration.between(start2, end2);
System.out.printf("%d 毫秒数\n", timeElapsed2.toMillis());
boolean overTenTimesFaster = timeElapsed.multipliedBy(10).minus(timeElapsed2).isNegative();
System.out.printf("第一个算法%s比第二个算法快十倍", overTenTimesFaster ? "" : "不");
}
public static void runAlgorithm() {
int size = 10;
ArrayList<Integer> list = new Random().ints().map(i -> i % 100).limit(size).boxed()
.collect(Collectors.toCollection(ArrayList::new));
Collections.sort(list);
System.out.println(list);
}
public static void runAlgorithm2() {
int size = 10;
ArrayList<Integer> list = new Random().ints().map(i -> i % 100).limit(size).boxed()
.collect(Collectors.toCollection(ArrayList::new));
while (!IntStream.range(1, list.size()).allMatch(i -> list.get(i - 1).compareTo(list.get(i)) <= 0)) {
Collections.shuffle(list);
}
System.out.println(list);
}
}