夯实Java基础(十四)——Java8新的日期处理类

一、前言

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

新增的日期经常使用的用这三个:java

  • java.time.LocalDate:只对年月日作出处理
  • java.time.LocalTime:只对时分秒纳秒作出处理
  • java.time.LocalDateTime :同时能够处理年月日和时分秒

二、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大都是通用的,全部后面两个的就不展现了。spa

方法使用举例:线程

 1 //now():获取当前日期
 2 LocalDate localDate=LocalDate.now();
 3 LocalTime localTime=LocalTime.now();
 4 LocalTime localTime1= LocalTime.now().withNano(0); // 这个是不带毫秒的
 5 LocalDateTime localDateTime=LocalDateTime.now();
 6 System.out.println("日期:"+localDate);
 7 System.out.println("时间:"+localTime);
 8 System.out.println("时间不带毫秒:"+localTime1);
 9 System.out.println("日期时间:"+localDateTime);
10  
11 //of():设置指定的年月日时分秒,没有偏移量
12 System.out.println("-----------");
13 LocalDateTime localDateTime2=LocalDateTime.of(2020, 04, 04, 18, 48, 56);
14 System.out.println("设置的时间为:"+localDateTime2);
15  
16 //getXXX:获取相关的属性
17 System.out.println("-----------");
18 System.out.println("这年的第几天:"+localDateTime.getDayOfYear());
19 System.out.println("这月的第几天:"+localDateTime.getDayOfMonth());
20 System.out.println("这月的第几天:"+localDateTime.getDayOfWeek());
21 System.out.println("月份为:"+localDateTime.getMonth());
22 System.out.println("月份为:"+localDateTime.getMonthValue());
23 System.out.println("小时为:"+localDateTime.getHour());
24  
25 //withXXX:设置相关的属性,体现了不可变性,修改后返回了新的对象
26 LocalDateTime localDateTime3=localDateTime.withDayOfMonth(22);
27 System.out.println("当前的时间:"+localDateTime);
28 System.out.println("修改月份后:"+localDateTime3);
29  
30 LocalDateTime localDateTime4=localDateTime.withHour(14);
31 System.out.println("当前的时间:"+localDateTime);
32 System.out.println("修改小时后:"+localDateTime4);
33  
34 //plusXXX:增长相关属性
35 LocalDateTime localDateTime5=localDateTime.plusDays(10);
36 System.out.println("当前时间:"+localDateTime);
37 System.out.println("相加以后:"+localDateTime5);
38  
39 //minusXXX:减小相关属性
40 LocalDateTime localDateTime6=localDateTime.minusDays(10);
41 System.out.println("当前时间:"+localDateTime);
42 System.out.println("相减以后:"+localDateTime6);

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

 1 /**
 2  * LocalDate ,LocalTime,LocalDateTime 互相转换
 3  */
 4 @Test
 5 public void test5(){
 6     String date = "2020-7-12";
 7     String time = "15:51:30";
 8     LocalDate localDate = LocalDate.parse(date);
 9     LocalTime localTime = LocalTime.parse(time);
10  
11     LocalDateTime localDateTime = LocalDateTime.of(2020, 7, 13, 16, 01, 30, 888);
12     LocalDateTime localDateTime1 = LocalDateTime.of(localDate, localTime);
13  
14     //localDateTime-->LocalDate,LocalTime
15     LocalDate localDate1 = localDateTime.toLocalDate();
16     LocalTime localTime1 = localDateTime.toLocalTime();
17  
18     // LocalDate,LocalTime --> LocalDateTime
19     LocalDateTime localDateTime2 = localDate.atTime(16, 02, 30);
20     LocalDateTime localDateTime3 = localTime.atDate(localDate);
21  
22 }

三、瞬时(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类的对象

方法使用举例:

 1 @Test
 2 public void testInstant() {
 3     //now():获取标准时间,即本初子午线的时间,没有偏移量
 4     Instant instant = Instant.now();
 5     System.out.println(instant);
 6         
 7     //atOffset:添加偏移量,北京在东八区,时区加八即为北京时间
 8     OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
 9     System.out.println(offsetDateTime);
10        
11     //toEpochMilli:获取1970-01-01 00:00:00 开始的毫秒;相似Date的getTime
12     long epochMilli = instant.toEpochMilli();
13     System.out.println(epochMilli);
14         
15     //ofEpochMilli:经过给定的毫秒数,获取Instant实例;相似Date(long millis)
16     Instant ofEpochMilli = Instant.ofEpochMilli(1562384592201L);
17     System.out.println(ofEpochMilli);
18 }

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

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

实例:

 1     @Test
 2     public void testDurationAndPeriod(){
 3         //Duration
 4         LocalDate date1 = LocalDate.of(2020, 7, 6);
 5         LocalDate date2 = LocalDate.of(2025, 9, 10);
 6         LocalTime time1 = LocalTime.of(15, 7, 50);
 7         LocalTime time2 = LocalTime.of(17, 8, 53);
 8         LocalDateTime dateTime1 = LocalDateTime.of(2020, 5, 12, 14, 22, 28);
 9         LocalDateTime dateTime2 = LocalDateTime.of(2024, 5, 12, 14, 22, 28);
10         Instant instant1 = Instant.ofEpochSecond(1);
11         Instant instant2 = Instant.now();
12         Duration d1 = Duration.between(time1, time2);
13         Duration d2 = Duration.between(dateTime1, dateTime2);
14         Duration d3 = Duration.between(instant1, instant2);
15         // 这里会抛异常java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds
16         //须要使用Period类进行操做日期
17         //Duration d4 = Duration.between(date1, date2);
18         System.out.println("LocalTime持续秒数:" + d1.getSeconds());
19         System.out.println("LocalDateTime持续秒数:" + d2.getSeconds());
20         System.out.println("Instant持续秒数" + d3.getSeconds());
21         
22         //Period
23         Period period=Period.between(date1, date2);
24         System.out.println(period.getYears());
25         System.out.println(period.getMonths());
26         System.out.println(period.getDays());
27         System.out.println(period.toTotalMonths());
28     }

五、日期校订器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):返回一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期,若是该日期已经符合要求,直接返回该对象

方法使用举例:

 1 @Test
 2 public void testTemporalAdjusters(){
 3     //dayOfWeekInMonth:返回这个月第二周星期二的日期
 4     LocalDate localDate1=LocalDate.of(2020,9,15);
 5     LocalDate localDate2 = localDate1.with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY));
 6     System.out.println("默认时间:"+localDate1);
 7     System.out.println("更改时间:"+localDate2);
 8     
 9     //firstDayOfMonth():这个月第一天
10     System.out.println("---------");
11     LocalDate localDate3=localDate1.with(TemporalAdjusters.firstDayOfMonth());
12     System.out.println("默认时间:"+localDate1);
13     System.out.println("更改时间:"+localDate3);
14     
15     //lastDayOfMonth():这个月最后一天
16     System.out.println("---------");
17     LocalDate localDate4=localDate1.with(TemporalAdjusters.lastDayOfMonth());
18     System.out.println("默认时间:"+localDate1);
19     System.out.println("更改时间:"+localDate4);
20     
21     //nextOrSame():获取周2时间,若是当前时间恰好是星期2,那么就返回当前时间
22     System.out.println("---------");
23     LocalDate localDate5 = localDate1.with(TemporalAdjusters.nextOrSame(DayOfWeek.TUESDAY));
24     System.out.println("默认时间:"+localDate1);
25     System.out.println("更改时间:"+localDate5);
26 }

运行结果:

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

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

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

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

有时间有日期:

 1 String datetime1="2019-05-24 18:15:56";
 2 DateTimeFormatter formatter1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 3 LocalDateTime localDateTime1=LocalDateTime.parse(datetime1,formatter1);
 4 System.out.println(localDateTime1);
 5  
 6 或者:
 7 String datetime2="2019-05-24 18:15:56";
 8 DateTimeFormatter formatter2=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 9 TemporalAccessor parse = formatter2.parse(datetime2);
10 LocalDateTime localDateTime=LocalDateTime.from(parse);
11 System.out.println(localDateTime);

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

  • 若是是LocalDate这种标准格式的,直接toString就能够了,
  • 若是是LocalTime这种格式的,toString会附带纳秒值21:06:30.760163, 这个时候你可使用日期格式器,或者这样 LocalTime time = LocalTime.now().withNano(0),把纳秒直接清0.
  • 若是是LocalDateTime,这个时候是须要一个日期转换器的。才能由时间+日期->想要的时间,
1 LocalDate localDate=LocalDate.now();
2 System.out.println(localDate.toString());
3         
4 DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
5 LocalDateTime localDateTime=LocalDateTime.now();
6 String result=localDateTime.format(formatter);
7 System.out.println(result);

七、JDBC中对应的日期

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

SQL -> Java

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

date -> LocalDate

time -> LocalTime

timestamp -> LocalDateTime

八、小结

此次主要学习了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,否则会报错。

更多用例查看此文: http://www.javashuo.com/article/p-cbjionju-be.html

相关文章
相关标签/搜索