Java8日期时间API详解

基本概念

Java8已经发布很长时间了,但是仍然有很多小伙伴不熟悉Java8的日期时间API。今天我们来一起学习一下。
首先了解几个概念,也就是日期时间在Java中所体现的几种形式,这几种形式是可以相互转换的。:

  • 时间戳
    long 长整型 1604030178372

指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。

  • 日期时间对象
    Clock:时钟 1604039715148
    Instant:瞬时 2020-10-30T06:35:15.148Z
    LocalDate:日期 2020-10-30
    LocalTime:时间 14:35:15.161
    LocalDateTime:日期时间 2020-10-30T14:35:15.162
    OffsetTime:偏移时间 14:35:15.162+08:00 (OffsetTime = LocalTime + ZoneOffset)
    OffsetDateTime:偏移日期时间 2020-10-30T14:35:15.162+08:00 (OffsetDateTime= LocalDateTime + ZoneOffset)
    ZonedDateTime:时区日期时间 2020-10-30T14:35:15.163+08:00[Asia/Shanghai] (ZonedDateTime= LocalDateTime + ZoneId)
  • 字符串
    String:文本 2020-10-302020-10-30 14:35:15
  • 时间间隔
    Duration:时间间隔 PT1H2M38S PT前缀,H表示小时,M表示分钟,S表示秒。

时区
ZoneId:时区ID Asia/Shanghai
ZoneOffset:时区偏移,继承ZoneId+08:00

ZoneIdZoneOffset区别:如果按照时区划分没啥区别。但是呢,时区是固定的。也就是ZoneId是固定的。ZoneOffset对其进行了扩展,可以任意调整偏移。
public static ZoneOffset ofHoursMinutesSeconds(int hours, int minutes, int seconds)

时区导致每个地区的时间是不一样的,比如现在北京时间10:00点,那么东京时间就是11:00点。相差一个小时。体现到代码上就是,同一个时间戳使用不同的时区进行转换得到的日期时间是有时差的

源码分析

  • Instant LocalDate LocalTime LocalDateTime OffsetTime OffsetDateTime ZonedDateTime
    这几个类都继承了Temporal
  • 其实一切的根源就在于一行代码,简直不要太熟悉。
		System.currentTimeMillis();

接下来我们一步一步分析这一行代码是如何创建的Java8日期时间API。

  • Clock
public abstract class Clock {
	// 1 静态方法创建Clock对象
	public static Clock systemDefaultZone() {
		return new SystemClock(ZoneId.systemDefault());
	}

	public long millis() {
		return instant().toEpochMilli();
	}

	public abstract Instant instant();
	// 静态内部类实现Clock
	static final class SystemClock extends Clock implements Serializable {
		// 时区
		private final ZoneId zone;
		SystemClock(ZoneId zone) {
			this.zone = zone;
		}
		// 获取毫秒数
		@Override
		public long millis() {
			return System.currentTimeMillis();
		}
		// 转换成Instant对象
		@Override
		public Instant instant() {
			return Instant.ofEpochMilli(millis());
		}
	}
}
  • LocalDateTime
public final class LocalDateTime implements Temporal, TemporalAdjuster, ChronoLocalDateTime<LocalDate>, Serializable {
	private final LocalDate date;
	private final LocalTime time;
	// 创建日期时间:Clock.systemDefaultZone()
	public static LocalDateTime now() {
		return now(Clock.systemDefaultZone());
	}
	
	public static LocalDateTime now(Clock clock) {
		Objects.requireNonNull(clock, "clock");
		final Instant now = clock.instant(); // called once
		ZoneOffset offset = clock.getZone().getRules().getOffset(now);
		return ofEpochSecond(now.getEpochSecond(), now.getNano(), offset);
	}
	// 通过秒、毫秒、时区偏移来创建LocalDateTime.
	public static LocalDateTime ofEpochSecond(long epochSecond, int nanoOfSecond, ZoneOffset offset) {
		Objects.requireNonNull(offset, "offset");
		NANO_OF_SECOND.checkValidValue(nanoOfSecond);
		long localSecond = epochSecond + offset.getTotalSeconds(); // overflow caught later
		long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY);
		int secsOfDay = (int) Math.floorMod(localSecond, SECONDS_PER_DAY);
		LocalDate date = LocalDate.ofEpochDay(localEpochDay);
		LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + nanoOfSecond);
		return new LocalDateTime(date, time);
	}
}

由此可以看出Clock每次获取都是新的毫秒数,而Temporal子类创建之后如果不修改的话就代表时间线上某一时刻的时间。

写到这里不想写了,太费劲了,奈何文笔太差。。。。
LocalDateTime举例,说白了,一个日期时间能有啥功能,首先我们得创建一个LocalDateTime对象吧。
加粗样式
创建完之后我怎么也得看看里边是啥吧:比如年、月、日、时、分、秒等。
在这里插入图片描述
一看发现某个字段值不对,可以通过如下方法重新设置。
在这里插入图片描述
然后呢,我还想跟别人创建的日期比较比较。
在这里插入图片描述
比较完之后感觉不行,比了半天输了,那就不服了。那咋办,比靠后输了那就加点时间呗,比靠前输了那就减点时间呗。反正得赢。
在这里插入图片描述
折腾半天可算赢了,不能白赢。得通知通知其他人庆祝一下呗。转成字符串,告诉String小老弟。在这里插入图片描述
转成其他日期时间对象。
在这里插入图片描述

常用功能案例

  • 获取日期时间
		LocalDateTime.now();
		LocalDateTime.of(2020, 10, 1, 10, 10, 10);
		LocalDateTime.parse("2020-10-01 10:10:10", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
  • 日期时间转字符串
		LocalDateTime dateTime = LocalDateTime.now();
		dateTime.format(DateTimeFormatter.ISO_DATE_TIME);
		dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
  • 字符串转日期时间
		String dateStr = "2020-01-01 11:11:11";
		LocalDateTime dateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
  • 日期时间转毫秒
		// 1秒 = 1000毫秒
		// 1毫秒 = 1000000纳秒
		LocalDateTime dateTime = LocalDateTime.now();
		long nano = dateTime.getNano();// 纳秒
		long second = dateTime.toEpochSecond(ZoneOffset.of("+08:00"));// 秒
		long milli = dateTime.toInstant(ZoneOffset.of("+08:00")).toEpochMilli();// 毫秒
  • 毫秒转日期时间
		long milli = 1604047456505l;
		LocalDateTime.ofInstant(Instant.ofEpochMilli(milli), ZoneId.systemDefault());
  • 当前时间是否在指定时间内
		LocalDateTime start = LocalDateTime.of(2020, 10, 1, 10, 10);// 2020-10-1 10:10
		LocalDateTime end = LocalDateTime.of(2020, 11, 2, 10, 10);// 2020-11-2 10:10
		LocalDateTime currTime = LocalDateTime.now();
		boolean isBetween = currTime.isAfter(start) && currTime.isBefore(end);
  • 比较两个时间
		LocalDateTime a = LocalDateTime.of(2020, 10, 1, 10, 10);// 2020-10-1 10:10
		LocalDateTime b = LocalDateTime.of(2020, 11, 2, 10, 10);// 2020-11-2 10:10
		boolean isAfter = a.isAfter(b);
		boolean isBefore = a.isBefore(b);
		boolean isEqual = a.isEqual(b);
		int result = a.compareTo(b);// a<b=-1;a=b=0;a>b=1
  • 获取两个时间的时间间隔
		LocalDateTime a = LocalDateTime.of(2020, 10, 1, 10, 10);// 2020-10-1 10:10
		LocalDateTime b = LocalDateTime.of(2020, 11, 2, 10, 10);// 2020-11-2 10:10
		Duration duration = Duration.between(a, b);
		long days = duration.toDays();
		long hours = duration.toHours();
		long minutes = duration.toMinutes();
		long millis = duration.toMillis();

如果还有其他没有涉及到的常用功能,可以在评论区留言。。。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值