在JDK1.8之前,日期和时间的处理一直是Java里面经常被吐槽的问题,相信使用过Date和Calendar的人都有深刻的感觉,不管你是要进行日期和时间的计算或者相互比较,在使用Date和Calendar时都表现的很麻烦,总之一句话就是不好用。
以至于在JDK1.8之前,很多人都选择使用joda-time来进行日期和时间的处理,joda-time对日期和时间的处理进行了封装,使日期和时间的处理变得简单
在JDK1.8中引入java.time.*包,重新定义了一套日期时间处理类, 让日期时间的处理变得简单易用
在介绍java.time包之前,先来聊一些基础概念,大家在处理时间的过程中,一定处理过时区,北京时间需要加8小时,相信只要开发过程中处理过时间,都会有这样一个操作,那为什么北京时间需要加8小时呢?
说来惭愧,在写这篇博文之前,我没有搞清楚这里面的逻辑,只知道北京属于东八区,需要加8小时,下面我们一起来看一下~
协调世界时(Coordinated Universal Time)又称世界统一时间、世界标准时间,由于英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。
由于世界各国家与地区经度不同,地方时也有所不同,因此会划分为不同的时区
地球是自西向东自转,东边比西边先看到太阳,东边的时间也比西边的早。东边时刻与西边时刻的差值不仅要以时计,而且还要以分和秒来计算,这给人们带来不便
为了克服时间上的混乱,1884年在华盛顿召开的一次国际经度会议(又称国际子午线会议)上,规定将全球划分为24个时区(东、西各12个时区)。规定英国(格林尼治天文台旧址)为中时区(零时区)、东1—12区,西1—12区。每个时区横跨经度15度,时间正好是1小时。最后的东、西第12区各跨经度7.5度,以东、西经180度为界。每个时区的中央经线上的时间就是这个时区内统一采用的时间,称为区时,相邻两个时区的时间相差1小时 《摘自百度百科》
因为北京属于东8区,所以需要在世界统一时间(UTC)的基础上加8小时
java.time包主要提供了日期、时间、瞬间、持续时间的api
主要的日期时间概念,包括时刻,持续时间,日期,时间,时区和时段。 基于ISO日历系统,所有的类都是不可变的,线程安全的
按类型主要分为:
下面来分别看一下各自的用法
Instant表示的是时间线上的瞬间点,本质上就是时间戳
Instant instant = Instant.now();
//默认时间比北京时间相差8小时
System.out.println(instant);// 2020-07-10T12:52:56.053Z
//设置时区后,显示正常时间
System.out.println(instant.atZone(ZoneId.systemDefault()));//2020-07-10T20:52:56.053+08:00[Asia/Shanghai]
//获取当前时间戳的秒数
System.out.println(instant.getEpochSecond());
//获取当前时间戳的毫秒
System.out.println(instant.toEpochMilli());
//Date类型转换为Instant
Instant instant1 = Instant.ofEpochMilli(new Date().getTime());
System.out.println(instant1);
//将字符串转换成Instant
Instant instant2 = Instant.parse("2020-07-10T12:52:56.053Z");
System.out.println(instant2);
//将Clock转换成Instant
Instant instant3 = Instant.now(Clock.systemUTC());
System.out.println(instant3);
//加3小时,注意加操作对instant对象本身来说没有影响
System.out.println(instant.plus(3, ChronoUnit.HOURS)); //2020-07-10T16:32:16.570Z
System.out.println(instant);//2020-07-10T13:32:16.570Z
Instant ins1 = Instant.parse("2020-07-10T12:52:56.053Z");
Instant ins2 = Instant.parse("2020-07-10T12:52:46.034Z");
//时间戳比较
System.out.println(ins1.isAfter(ins2));
System.out.println(ins1.isBefore(ins2));
LocalDate是一个不可变的日期时间对象,存储没有时间的日期
LocalDate localDate = LocalDate.now();
System.out.println(localDate); //2020-07-10
//Clock转换成LocalDate
LocalDate localDate1 = LocalDate.now(Clock.systemDefaultZone());
System.out.println(localDate1); //2020-07-10
//指定年月日的LocalDate
LocalDate localDate2 = LocalDate.of(2020,5,1);
System.out.println(localDate2); //2020-05-01
//字符串转换成LocalDate
LocalDate localDate3 = LocalDate.parse("2020-05-04");
System.out.println(localDate3); //2020-05-04
//指定格式化规则的转换
LocalDate localDate4 = LocalDate.parse("20200205",DateTimeFormatter.ofPattern("yyyyMMdd"));
System.out.println(localDate4); //2020-02-05
//2020年的第100天
LocalDate localDate5 = LocalDate.ofYearDay(2020,100);
System.out.println(localDate5); //2020-04-09
//加4天
System.out.println(localDate.plusDays(4)); // 2020-07-14
System.out.println(localDate.plus(4,ChronoUnit.DAYS)); // 2020-07-14
//两周后
System.out.println(localDate.plusWeeks(2)); //2020-07-24
//两月后
System.out.println(localDate.plusMonths(2)); //2020-09-10
//两年后
System.out.println(localDate.plusYears(2)); //2022-07-10
//3天前
System.out.println(localDate.plusDays(-3));// 2020-07-07
System.out.println(localDate.minusDays(3));//2020-07-07
//4天后是星期几
System.out.println(localDate.plusDays(4).getDayOfWeek()); //TUESDAY
//localDate所代表的日期是当月的第几天
System.out.println(localDate.getDayOfMonth());
//localDate所代表的日期是今年的第多少天
System.out.println(localDate.getDayOfYear());
//日期格式化
System.out.println(localDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))); //2020/07/10
//是否闰年
System.out.println(localDate.isLeapYear());
//当月有多少天
System.out.println(localDate.lengthOfMonth());
//当年有多少天
System.out.println(localDate.lengthOfYear());
LocalTime是一个不可变的日期时间对象,存储没有日期的时间
LocalTime localTime = LocalTime.now();
System.out.println(localTime); //22:42:42.520
//时:分
System.out.println(LocalTime.of(12,11)); // 12:11
//时:分:秒
System.out.println(LocalTime.of(12,11,45)); //12:11:45
//加2小时
System.out.println(localTime.plusHours(2)); //12:11:45
...
//LocalTime的很多方法和操作跟LocalDate都是一样的,这里不再赘述
LocalDateTime是一个不可变的日期时间对象,代表日期时间
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime); //2020-07-10T22:52:33.898
//日期时间格式化
System.out.println(localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss")));
//10天后是星期几
System.out.println(localDateTime.plusDays(10).getDayOfWeek());
//17分钟后
System.out.println(localDateTime.plusMinutes(17));
LocalDateTime相当于是结合了LocalDate和LocalTime,方法和功能也都是一样的
ZonedDateTime是具有时区的日期时间的不可变表示
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime); //2020-07-10T22:57:05.830+08:00[Asia/Shanghai]
//转换成LocalDate
System.out.println(zonedDateTime.toLocalDate()); //2020-07-10
//转换成LocalDateTime
System.out.println(zonedDateTime.toLocalDateTime());//2020-07-10T22:59:09.501
//转换成LocalTime
System.out.println(zonedDateTime.toLocalTime());//22:59:09.501
//加3天
System.out.println(zonedDateTime.plusDays(3));//2020-07-13T23:00:07.716+08:00[Asia/Shanghai]
//格式化
System.out.println(zonedDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss")));
//其他方式请参考 locateDate 和 localTime
Duration描述的其实是时长,表示一个时间区间
//定义5天
Duration duration = Duration.of(5,ChronoUnit.DAYS);
System.out.println(duration); //PT120H
//3小时
System.out.println(Duration.ofHours(3)); //PT3H
//输出小时
System.out.println(Duration.of(5,ChronoUnit.DAYS).toHours());
//加8小时(5天8小时)
System.out.println(duration.plusHours(8).toHours()); //128
上面已经介绍了常用的日期时间类型的使用,基本上日常的使用通过上面的几个类就够用了,其他类型(Month、DayOfWeek、Year、YearMonth、MonthDay、OffsetTime、OffsetDateTime)的用法都是大同小异,看一下api基本都会了
从上面一些类的用法,可以看出JDK1.8对日期时间类的处理定义了很多类,用来表示不同的日期时间使用场景,基本上我们常用到的场景,都有定义不同的类,通过这些类可以很方便的操作日期和时间。
如果感觉对你有些帮忙,请收藏好,你的关注和点赞是对我最大的鼓励!
如果想跟我一起学习,坚信技术改变世界,请关注【Java天堂】公众号,我会定期分享自己的学习成果,第一时间推送给您