1、前言

Java8之前处理日期一直是Java程序员比较头疼的问题,从Java 8之后,Java里面添加了许多的新特性,其中一个最常见也是最实用的便是日期处理的类——LocalDate。LocalDate是一种更为高效的日期类,比起Date的复杂具有相当高的简洁性,吸取了企业级别的joda.time时间处理的优点,避免了传统的Date和Calendar复合起来计算的难处。

新增的日期常用的用这三个:

  • java.time.LocalDate:只对年月日做出处理
  • java.time.LocalTime:只对时分秒纳秒做出处理
  • java.time.LocalDateTime :同时可以处理年月日和时分秒

2、LocalDate、LocalTime、LocalDateTime

LocalDate:代表IOS格式(yyyy-MM-hh)的日期,不包含具体时间的日期,比如2014-01-14。它可以用来存储生日,周年纪念日,入职日期等。

LocalTime:它代表的是不含日期的时间;

LocalDateTime:它包含了日期及时间,不过还是没有偏移信息或者说时区,比较常用;

它们三者共同特点:

  • 相比于前面的Date和Calendar,他们是线程安全的;
  • 它们是不可变的日期时间对象;

常用方法:

  • now() 、 now(Zoneld zone):静态方法,根据当前时间创建对象 、 指定时区的对象
  • of() :静态方法,根据指定日期,时间创建对象
  • getDayOfMonth():获得月份天数(1-31)
  • getDayOfYear():获取年份天数(1-366)
  • getDayOfWeek():获得星期几
  • getYear():获得年份
  • getMonth() 、 getMonthValue(): 获得月份(返回枚举值如:January) 、 返回数字(1-12)
  • getHour()、getMinute()、getSecond():获得当前对象的时、分、秒
  • withDayOfMonth()、withDayOfYear()、withMonth()、withYear():将月份天数、年份天数、月份、年份修改为指定的值并且返回新的对象,因为LocalDate等是不变性的
  • plusDays()、plusWeeks()、plusMonths()、plusYears()、plusHours():向当前对象添加几天、几周、几个月、几年,几小时
  • minusDays()、minusWeeks()、minusMonths()、minusYears()、minusHours():从当前对象减去几月、几周、几个月、几年、几小时
  • isLeapYear():判断是否为闰年
  • isBefore、isEqual、isAfter:检查日期是否在指定日期前面,相等,后面

由于LocalDate的API与LocalTime、LocalDateTime大都是通用的,所有后面两个的就不展示了。

方法使用举例:

 //now():获取当前日期
 LocalDate localDate=LocalDate.now();
 LocalTime localTime=LocalTime.now();
 LocalTime localTime1= LocalTime.now().withNano(0); // 这个是不带毫秒的
 LocalDateTime localDateTime=LocalDateTime.now();
 System.out.println("日期:"+localDate);
 System.out.println("时间:"+localTime);
 System.out.println("时间不带毫秒:"+localTime1);
 System.out.println("日期时间:"+localDateTime);

 //of():设置指定的年月日时分秒,没有偏移量
 System.out.println("-----------");
 LocalDateTime localDateTime2=LocalDateTime.of(2020, 04, 04, 18, 48, 56);
 System.out.println("设置的时间为:"+localDateTime2);

 //getXXX:获取相关的属性
 System.out.println("-----------");
 System.out.println("这年的第几天:"+localDateTime.getDayOfYear());
 System.out.println("这月的第几天:"+localDateTime.getDayOfMonth());
 System.out.println("这月的第几天:"+localDateTime.getDayOfWeek());
 System.out.println("月份为:"+localDateTime.getMonth());
 System.out.println("月份为:"+localDateTime.getMonthValue());
 System.out.println("小时为:"+localDateTime.getHour());

 //withXXX:设置相关的属性,体现了不可变性,修改后返回了新的对象
 LocalDateTime localDateTime3=localDateTime.withDayOfMonth(22);
 System.out.println("当前的时间:"+localDateTime);
 System.out.println("修改月份后:"+localDateTime3);

 LocalDateTime localDateTime4=localDateTime.withHour(14);
 System.out.println("当前的时间:"+localDateTime);
 System.out.println("修改小时后:"+localDateTime4);

 //plusXXX:增加相关属性
 LocalDateTime localDateTime5=localDateTime.plusDays(10);
 System.out.println("当前时间:"+localDateTime);
 System.out.println("相加之后:"+localDateTime5);

 //minusXXX:减少相关属性
 LocalDateTime localDateTime6=localDateTime.minusDays(10);
 System.out.println("当前时间:"+localDateTime);
 System.out.println("相减之后:"+localDateTime6);

LocalDate ,LocalTime ,LocalDateTime 它们之间的互相转换: 

 /**
  * LocalDate ,LocalTime,LocalDateTime 互相转换
  */
 @Test
 public void test5(){
     String date = "2020-7-12";
     String time = "15:51:30";
     LocalDate localDate = LocalDate.parse(date);
     LocalTime localTime = LocalTime.parse(time);

     LocalDateTime localDateTime = LocalDateTime.of(2020, 7, 13, 16, 01, 30, 888);
     LocalDateTime localDateTime1 = LocalDateTime.of(localDate, localTime);

     //localDateTime-->LocalDate,LocalTime
     LocalDate localDate1 = localDateTime.toLocalDate();
     LocalTime localTime1 = localDateTime.toLocalTime();

     // LocalDate,LocalTime --> LocalDateTime
     LocalDateTime localDateTime2 = localDate.atTime(16, 02, 30);
     LocalDateTime localDateTime3 = localTime.atDate(localDate);

 }

3、瞬时(Instant)

Instant类:时间线上的一个瞬时点,设计初衷是为了便于机器使用,不提供人类意义上的时间单位,获取当前时刻的时间戳;它只是简单的从1970年1月1日0时0分0秒(UTC)开始的秒数。

常用方法:

  • now():静态方法,返回默认的UTC时区的Instant类的对象
  • atOffset(ZoneOffset offset):将此瞬间与偏移组合起来创建一个OffsetDateTime
  • toEpochMilli():返回1970-01-01 00:00:00到当前的毫秒数,即时间戳
  • ofEpochMilli(long epochMilli):静态方法,返回在1970-01-01 00:00:00基础加上指定毫秒数之后的Instant类的对象
  • ofEpochSecond(long epochSecond):静态方法,返回在1970-01-01 00:00:00基础加上指定秒数之后的Instant类的对象

方法使用举例:

 @Test
 public void testInstant() {
     //now():获取标准时间,即本初子午线的时间,没有偏移量
     Instant instant = Instant.now();
     System.out.println(instant);

     //atOffset:添加偏移量,北京在东八区,时区加八即为北京时间
     OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
     System.out.println(offsetDateTime);

     //toEpochMilli:获取1970-01-01 00:00:00 开始的毫秒;类似Date的getTime
     long epochMilli = instant.toEpochMilli();
     System.out.println(epochMilli);

     //ofEpochMilli:通过给定的毫秒数,获取Instant实例;类似Date(long millis)
     Instant ofEpochMilli = Instant.ofEpochMilli(1562384592201L);
     System.out.println(ofEpochMilli);
 }

4、日期间隔,持续时间 (Period 和 Duration)

Java 8 中还引入的两个与日期相关的新类:Period 和 Duration。两个类分别表示时间量或两个日期之间的差,两者之间的差异为:Period基于日期值,而Duration基于时间值。

实例:

     @Test
     public void testDurationAndPeriod(){
         //Duration
         LocalDate date1 = LocalDate.of(2020, 7, 6);
         LocalDate date2 = LocalDate.of(2025, 9, 10);
         LocalTime time1 = LocalTime.of(15, 7, 50);
         LocalTime time2 = LocalTime.of(17, 8, 53);
         LocalDateTime dateTime1 = LocalDateTime.of(2020, 5, 12, 14, 22, 28);
         LocalDateTime dateTime2 = LocalDateTime.of(2024, 5, 12, 14, 22, 28);
         Instant instant1 = Instant.ofEpochSecond(1);
         Instant instant2 = Instant.now();
         Duration d1 = Duration.between(time1, time2);
         Duration d2 = Duration.between(dateTime1, dateTime2);
         Duration d3 = Duration.between(instant1, instant2);
         // 这里会抛异常java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds
         //需要使用Period类进行操作日期
         //Duration d4 = Duration.between(date1, date2);
         System.out.println("LocalTime持续秒数:" + d1.getSeconds());
         System.out.println("LocalDateTime持续秒数:" + d2.getSeconds());
         System.out.println("Instant持续秒数" + d3.getSeconds());

         //Period
         Period period=Period.between(date1, date2);
         System.out.println(period.getYears());
         System.out.println(period.getMonths());
         System.out.println(period.getDays());
         System.out.println(period.toTotalMonths());
     }

5、日期校正器TemporalAdjusters

到现在你所看到的所有日期操作都是相对比较直接的。有的时候,你需要进行一些更加 复杂的操作,比如,将日期调整到下个周日、下个工作日,或者是本月的最后一天。这时,你可以使用重载版本的with方法,向其传递一个提供了更多定制化选择的TemporalAdjusters对象, 更加灵活地处理日期。对于最常见的用例,日期和时间API已经提供了大量预定义的 TemporalAdjusters。你可以通过TemporalAdjusters类的静态工厂方法访问它们,如下所示:

下面是TemporalAdjusters类中的方法:

  • dayOfWeekInMonth(int ordinal,DayOfWeek dayOfWeek):返回一个新的日期,它的值为同一个月中每一周的第几天
  • firstDayOfMonth():返回一个新的日期,它的值为当月的第一天
  • firstDayOfNextMonth():返回一个新的日期,它的值为下月的第一天
  • firstDayOfNextYear():返回一个新的日期,它的值为明年的第一天
  • firstDayOfYear():返回一个新的日期,它的值为当年的第一天
  • firstInMonth(DayOfWeek dayOfWeek):返回一个新的日期,它的值为同一个月中,第一个符合星期几要求的值
  • lastDayOfMonth():返回一个新的日期,它的值为当月的最后一天
  • lastDayOfNextMonth():返回一个新的日期,它的值为下月的最后一天
  • lastDayOfNextYear():返回一个新的日期,它的值为明年的最后一天
  • lastDayOfYear():返回一个新的日期,它的值为今年的最后一天
  • lastInMonth(DayOfWeek dayOfWeek):返回一个新的日期,它的值为同一个月中,最后一个符合星期几要求的值
  • next(DayOfWeek dayOfWeek)、previous(DayOfWeek dayOfWeek):返回一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期
  • nextOrSame(DayOfWeek dayOfWeek)、previousOrSame(DayOfWeek dayOfWeek):返回一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期,如果该日期已经符合要求,直接返回该对象

方法使用举例:

 @Test
 public void testTemporalAdjusters(){
     //dayOfWeekInMonth:返回这个月第二周星期二的日期
     LocalDate localDate1=LocalDate.of(2020,9,15);
     LocalDate localDate2 = localDate1.with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY));
     System.out.println("默认时间:"+localDate1);
     System.out.println("更改时间:"+localDate2);

     //firstDayOfMonth():这个月第一天
     System.out.println("---------");
     LocalDate localDate3=localDate1.with(TemporalAdjusters.firstDayOfMonth());
     System.out.println("默认时间:"+localDate1);
     System.out.println("更改时间:"+localDate3);

     //lastDayOfMonth():这个月最后一天
     System.out.println("---------");
     LocalDate localDate4=localDate1.with(TemporalAdjusters.lastDayOfMonth());
     System.out.println("默认时间:"+localDate1);
     System.out.println("更改时间:"+localDate4);

     //nextOrSame():获取周2时间,如果当前时间刚好是星期2,那么就返回当前时间
     System.out.println("---------");
     LocalDate localDate5 = localDate1.with(TemporalAdjusters.nextOrSame(DayOfWeek.TUESDAY));
     System.out.println("默认时间:"+localDate1);
     System.out.println("更改时间:"+localDate5);
 }

运行结果:

6、Java 8日期解析和格式化(DateTimeFormatter)

之前格式化有SimpleDateFormat和DateFormat,但是它们两者都是线程不安全的!啥情况下会有这样的问题呢?如果我们为了实现日期转换这样的工具,每次都new一个对象,但是用完了就不用了,就造成了浪费,为此我们会将它写成单例的,但是单例的同时,一个对象供多个线程使用的时候,就会出现线程安全的问题。这个时候就需要这个新的jdk8出的DateTimeformatter这个类。
由字符串转为日期的方法:

如果是默认的格式,yyyy-MM-dd 这种日期格式字符串,直接用LocalDate.parse()进行转换就行了,相对应的时间也是。既有时间又有日期的用DateTimeformatte这个类就行。

 String time="2019-02-16";
 LocalDate localDate=LocalDate.parse(time);
 System.out.println(localDate);

有时间有日期:

 String datetime1="2019-05-24 18:15:56";
 DateTimeFormatter formatter1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 LocalDateTime localDateTime1=LocalDateTime.parse(datetime1,formatter1);
 System.out.println(localDateTime1);

 或者:
 String datetime2="2019-05-24 18:15:56";
 DateTimeFormatter formatter2=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 TemporalAccessor parse = formatter2.parse(datetime2);
 LocalDateTime localDateTime=LocalDateTime.from(parse);
 System.out.println(localDateTime);

由日期转为字符串的方法:

  • 如果是LocalDate这种标准格式的,直接toString就可以了,
  • 如果是LocalTime这种格式的,toString会附带纳秒值21:06:30.760163, 这个时候你可以使用日期格式器,或者这样 LocalTime time = LocalTime.now().withNano(0),把纳秒直接清0.
  • 如果是LocalDateTime,这个时候是需要一个日期转换器的。才能由时间+日期->想要的时间,
 LocalDate localDate=LocalDate.now();
 System.out.println(localDate.toString());

 DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 LocalDateTime localDateTime=LocalDateTime.now();
 String result=localDateTime.format(formatter);
 System.out.println(result);

7、JDBC中对应的日期

最新JDBC映射将把数据库的日期类型和Java 8的新类型关联起来:

SQL -> Java

---------------------

date -> LocalDate

time -> LocalTime

timestamp -> LocalDateTime

8、小结

这次主要学习了Java8中新的日期处理类

  1. LocalDate、LocalTime、LocalDateTime处理日期时间都非常的方便,而且它们是线程安全的,
  2. 新版的日期和时间API中,日期和时间对象是不可变的。
  3. LocalDate日期是一个便于使用的日期类,线程安全,Date类比较复杂,时间计算麻烦。
  4. DateTimeFormatter的使用也安全,方便。以后用它来代替SimpleDateFormat
  5. TemporalAdjuster 让你能够用更精细的方式操纵日期,不再局限于一次只能改变它的 一个值,并且你还可按照需求定义自己的日期转换器
  6. JDBC的TimeStamp类和LocalDateTime的转换也很方便,提供了相应的方法。
  7. 使用的时候,日期必须是标准的yyyy-MM-dd格式,比如1月必须写成01,不然会报错。

更多用例查看此文: https://www.cnblogs.com/comeboo/p/5378922.html

夯实Java基础(十四)——Java8新的日期处理类的更多相关文章

  1. Java基础20:Java8新特性终极指南

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  2. 对Java8新的日期时间类的学习(一)

    引用自Java译站http://it.deepinmind.com/java/2015/03/17/20-examples-of-date-and-time-api-from-Java8.html 除 ...

  3. Java基础(十四)--装箱、拆箱详解

    Java中基本数据类型都有相对应的包装类 什么是装箱?什么是拆箱? 在Java SE5之前,Integer是这样初始化的 Integer i = new Integer(10); 而在从Java SE ...

  4. 夯实Java基础(四)——面向对象之多态

    1.多态介绍 面向对象三大特征:封装.继承.多态.多态是Java面向对象最核心,最难以理解的内容.从一定角度来看,封装和继承几乎都是为多态而准备的. 多态就是指程序中定义的引用变量所指向的具体类型和通 ...

  5. java基础(十四)-----详解匿名内部类——Java高级开发必须懂的

    在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意的事项.匿名内部类使用的形参为何要为final. 使用匿名内部类内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式如下: n ...

  6. 对Java8新的日期时间类的学习(二)

    示例11 在Java中如何判断某个日期是在另一个日期的前面还是后面 这也是实际项目中常见的一个任务.你怎么判断某个日期是在另一个日期的前面还是后面,或者正好相等呢?在Java 8中,LocalDate ...

  7. Java8新特性-日期相关类操作

    JDK8以前使用SImpleDateFormate类格式化日期,因为在SImple DateFormate中存在Calendar实例引用,而在caleander中得establish中存在clear( ...

  8. 夯实Java基础系列目录

    自进入大学以来,学习的编程语言从最初的C语言.C++,到后来的Java,. NET.而在学习编程语言的同时也逐渐决定了以后自己要学习的是哪一门语言(Java).到现在为止,学习Java语言也有很长一段 ...

  9. 夯实Java基础(二十二)——Java8新特性之Lambda表达式

    1.前言 Java 8于14年发布到现在已经有5年时间了,经过时间的磨练,毫无疑问,Java 8是继Java 5(发布于2004年)之后的又一个非常最重要的版本.因为Java 8里面出现了非常多新的特 ...

随机推荐

  1. Requests方法 -- cookie绕过验证码登录操作

    前言有些登录的接口会有验证码:短信验证码,图形验证码等,这种登录的话验证码参数可以从后台获取的(或者查数据库最直接).获取不到也没关系,可以通过添加 cookie 的方式绕过验证码. 1.这里以登录博 ...

  2. 第七章 手动部署Fisco Bcos 区块链并完成新增群组,在原有群组中新增机构

    鉴于笔者以前各大博客教程都有很多人提问,早期建立一个技术交流群,里面技术体系可能比较杂,想了解相关区块链开发,技术提问,请加QQ群:538327407 目标 1.新增群组搭建完整联盟链 2.根据群组新 ...

  3. MySQL5.7高版本 疑似内存泄露

    I have an instance running on mysql-5.7.19. However, I found that its physical memory and virtual me ...

  4. flutter 如何实现文件读写(使用篇)

    flutter文件读写可以对磁盘文件进行操作,实现某些业务场景,那么我们开始来讲下这个文件读写操作. 使用的库插件(package) dart:io(用于数据处理) path_provider (用于 ...

  5. Codeforces 730A:Toda 2(multiset模拟)

    http://codeforces.com/problemset/problem/730/A 题意:有n个人打天梯,想让这n个人的分数相同,每场比赛必须有2-5个人参赛,参赛的人会降低一分,问一个合理 ...

  6. 字符串匹配问题(暴力,kmp)

    对于字符串的匹配问题,现在自己能够掌握的就只有两种方法, 第一种就是我们常用的暴力匹配法,那什么是暴力匹配法呢? 假设我们现在有一个文本串和一个模式串,我们现在要找出模式串在文本串的哪个位置. 文本串 ...

  7. [AI开发]目标跟踪之行为分析

    基于视频结构化的应用中,目标在经过跟踪算法后,会得到一个唯一标识和它对应的运动轨迹,利用这两个数据我们可以做一些后续工作:测速(交通类应用场景).计数(交通类应用场景.安防类应用场景)以及行为检测(交 ...

  8. Effective Java第三版(一) ——用静态工厂代替构造器

    此文做为<Effective Java>系列的第一篇,所以有必要大概说下此书的特点,当然很多人可能都看过,毕竟是有着Java四大名著之一的大名在外,不过总会有萌新不了解,例如我!<E ...

  9. 数字IC前后端设计中的时序收敛(二)--Setup违反的修复方法

    本文转自:自己的微信公众号<数字集成电路设计及EDA教程> 里面主要讲解数字IC前端.后端.DFT.低功耗设计以及验证等相关知识,并且讲解了其中用到的各种EDA工具的教程. 考虑到微信公众 ...

  10. python无网安装psycopg2

    1. 问题描述 ​ python项目要获取greenplum数据库数据,gp底层是postgresql,需要使用python的第三方工具包psycopg2操作数据库,但是问题是服务器上没有网络,无法在 ...