Java 8新特性之Date & Time

Java 8新特性之方法引用
Java 8新特性之Stream
Java 8新特性之Lambda


Java 8 之前使用的时间类:Date存在缺点:

Not thread safe - java.util.Date是非线程安全的,使用时必须处理并发问题。而新的时间类是不可变的,并且没有 set 方法。
Poor design - java.util.Date中日期从1900开始,月从1开始,天从0开始,十分不统一;原来的API提供了很少的时间操作。
Difficult time zone handing - 原来的API需要花费大量代码处理区域时间。

Java 8 加入了新的API:java.time

Java.time包中的是类是不可变且线程安全的。新的时间及日期API位于java.time中

  • Local - 简单时间API
  • Zoned - 区域时间API
    * Instance 			    时间戳
    * LocalDate			    不包含时间的日期
    * LocalTime 			不包含日期的时间
    * LocalDateTime 		包含时间及日期(没有偏移信息/时区)
    * ZonedDateTime 		包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。
    

基础学习

LocalDate、LocalTime和LocalDateTime。。(Instant)

LocalDate
  • 	LocalDate date = LocalDate.of(2014,3,18);
        int year = date.getYear();      
        Month month = date.getMonth();
        int day = date.getDayOfMonth();
        DayOfWeek dow = date.getDayOfWeek();	星期几
        int len = date.lengthOfMonth();		这个月有几天
        boolean leap = date.isLeapYear();
        LocalDate today = LocalDate.now();	当前日期
    
    	//使用Temporal读取LocalDate的值
    	int year1= date.get(ChronoField.YEAR);
        int month1= date.get(ChronoField.MONTH_OF_YEAR);
        int day1= date.get(ChronoField.DAY_OF_MONTH);
    
  • 运行结果:

    2014-03-18
    2014
    MARCH
    18
    TUESDAY
    31
    false
    2019-12-23
    
    2014
    3
    18
    
LocalTime
  •     LocalTime time = LocalTime.of(13,45,20);
        int hour = time.getHour();
        int minute = time.getMinute();
        int second = time.getSecond();
    
    	//也可以使用重载方法,自定义如何格式化日期
        LocalDate date1 = LocalDate.parse("2014-03-18");
        LocalTime time1 = LocalTime.parse("13:45:20");
    
  • 运行结果:

    13:45:20
    13
    45
    20
    
    2014-03-18
    13:45:20
    
LocalDateTime
  •    LocalDate date = LocalDate.parse("2014-03-18");
       LocalTime time = LocalTime.parse("13:45:20");
    
       LocalDateTime dt1 = LocalDateTime.of(2014,Month.MARCH,18,13,45,20);
       LocalDateTime dt2 = LocalDateTime.of(date,time);
       //date加一个time转换成LocalDateTime
       LocalDateTime dt3 = date.atTime(13,15,20);
       LocalDateTime dt4 = date.atTime(time);
       //time加一个date转换成LocalDateTime
       LocalDateTime dt5 = time.atDate(date);
    
       LocalDate date1 = dt1.toLocalDate();
       LocalTime time1 = dt1.toLocalTime();
    
  • 运行结果

    2014-03-18T13:45:20
    2014-03-18T13:45:20
    2014-03-18T13:15:20
    2014-03-18T13:45:20
    2014-03-18T13:45:20
    
    2014-03-18
    13:45:20
    
Instant(目前我也不知道这啥)
  • 	Instant i1 = Instant.ofEpochSecond(3);
    	Instant i2 = Instant.ofEpochSecond(3,0);
    	Instant i3 = Instant.ofEpochSecond(2,1000000000);
    	Instant i4 = Instant.ofEpochSecond(4,-1000000000);
    
  • 运行结果:

    1970-01-01T00:00:03Z
    1970-01-01T00:00:03Z
    1970-01-01T00:00:03Z
    1970-01-01T00:00:03Z
    

Duration(持续)、Period(期间)

Duration(时间间隔)
  •     LocalTime time1 = LocalTime.of(13,45,20);
        LocalTime finalTime = time1 .plus(Duration.ofSeconds(30));
        LocalTime time2 = LocalTime.of(14,48,50);
        
        LocalDateTime dateTime1 = LocalDateTime.of(2014,Month.MARCH,18,13,45,20);
        LocalDateTime dateTime2 = LocalDateTime.of(2016,Month.MARCH,20,15,50,50);
        
        Instant instant1 = Instant.ofEpochSecond(4,-1000000000);
        Instant instant2 = Instant.ofEpochSecond(2,1000000000);
      
      
        Duration d1 = Duration.between(time1,time2);
        Duration d2 = Duration.between(dateTime1,dateTime2);
        Duration d3 = Duration.between(instant1,instant2);
      
        Period tenDays = Period .between(LocalDate.of(2014,3,8)
                ,LocalDate.of(2014,3,18));
      
        /**************/
        LocalTime time = LocalTime.now();
        LocalTime time2 = time.plusMinutes(1).plusSeconds(20);
        Duration between = Duration.between(time, time2);
        long distance = Duration.between(time, time2).getSeconds();
        long distance2 = ChronoUnit.SECONDS.between(time, time2);
    
  • 运行结果

    PT1H3M30S
    PT17594H5M30S
    //此处没有给出运行结果
    PT0S
    
    P10D
    
    /***********/
    PT1M20S
    80
    80
    
Period(日期间隔)
  • 	Duration threeMinutes = Duration.ofMinutes(3);
    	Duration threeMinutes2 = Duration.of(3,ChronoUnit.MINUTES);
    	
    	Period tenDays2 = Period.ofDays(10);
    	Period threeWeeks = Period.ofWeeks(3);
    	Period twoYearsSixMonthsOneDay = Period.of(2,6,1);
    
    	LocalDate date1 = LocalDate.parse("2018-01-01");
        LocalDate date2 = LocalDate.parse("2019-02-02");
        Period dd = Period.between(date1,date2);
        int days = Period.between(date1, date2).getDays();	//这块是一个小坑,排除月份的日期相减
        long days2 = ChronoUnit.DAYS.between(date1, date2);
    
  • 运行结果

    PT3M
    PT3M
    
    P10D
    P21D
    P2Y6M1D
    
    date   P1Y1M1D
    days   1
    days2  397
    

操纵(TemporalAdjuster)、解析、格式化日期

操纵日期

普通方式
  •   		LocalDate date = LocalDate.of(2014,3,18);
              //直观方式操纵LocalDate属性
              LocalDate date1 = date.withYear(2011);
              LocalDate date2 = date.withDayOfYear(25);
              LocalDate date3 = date.with(ChronoField.MONTH_OF_YEAR,9);
      
              //以相对方式修改LocalDate属性
              date1 = date.plusWeeks(1);
              date2 = date.minusYears(3);
              date3 = date.plus(6,ChronoUnit.MONTHS);
    
  • 运行结果:

    2014-03-18
    2011-03-18
    2014-01-25
    2014-09-18
    
    2014-03-18
    2014-03-25
    2011-03-18
    2014-09-18
    
TemporalAdjuster操纵日期
  •   	LocalDate date1 = LocalDate.of(2014,3,18);
      	LocalDate date2 = date1.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
      	LocalDate date3 = date2.with(TemporalAdjusters.lastDayOfMonth());
    
  • 运行结果

    2014-03-18
    2014-03-23
    2014-03-31
    
方法 描述
dayOfWeekInMonth 创建一个新的日期,它的值为同一个月中每一周的第几天
firstDayOfMonth 创建一个新的日期,它的值为当月的第一天
firstDayOfNextMonth 创建一个新的日期,它的值为下月的第一天
firstDayOfNextYear 创建一个新的日期,它的值为明年的第一天
firstDayOfYear 创建一个新的日期,它的值为当年的第一天
firstInMonth 创建一个新的日期,它的值为同一个月中,第一个符合星期几要求的值
lastDayOfMonth 创建一个新的日期,它的值为当月的最后一天
lastDayOfNextMonth 创建一个新的日期,它的值为下月的最后一天
lastDayOfNextYear 创建一个新的日期,它的值为明年的最后一天
lastDayOfYear 创建一个新的日期,它的值为今年的最后一天
lastInMonth 创建一个新的日期,它的值为同一个月中,最后一个符合星期几要求的值
next / previous 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期
nextOrSame / previousOrSame 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期,如果该日期已经符合要求,直接返回该对象

格式化、解析日期-时间对象

  •   	LocalDate date = LocalDate.of(2014,3,18);
      	//使用本来就有的格式转化为字符串
      	String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE);
      	String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
      	
      	LocalDate date1 = LocalDate.parse("20140318",DateTimeFormatter.BASIC_ISO_DATE);
          LocalDate date2 = LocalDate.parse("2014-03-18",DateTimeFormatter.ISO_LOCAL_DATE);
      	//使用自己设定的格式转化为字符串
      	DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
      	String formattedDate = date.format(formatter);
      	LocalDate date3 = LocalDate.parse(formattedDate, formatter);
      
      	DateTimeFormatter italianFormatter = DateTimeFormatter.ofPattern("d.MMMM yyyy", Locale.ITALIAN);
          formattedDate = date.format((italianFormatter));
          date3 = LocalDate.parse(formattedDate,italianFormatter);
    
  • 运行结果

    2014-03-18
    
    20140318
    2014-03-18
    
    2014-03-18
    2014-03-18
    
    2014-03-18
    Value(DayOfMonth,2)'/'Value(MonthOfYear,2)'/'Value(YearOfEra,4,19,EXCEEDS_PAD)
    18/03/2014
    2014-03-18
    
    Value(DayOfMonth)'.'Text(MonthOfYear)' 'Value(YearOfEra,4,19,EXCEEDS_PAD)
    18.marzo 2014
    2014-03-18
    

处理不同时区(这里有点难)

示例一 、大陆-东京时区啥啥啥

  •   //由localDateTime 获取tokyoDateTime 
      LocalDateTime localDateTime = LocalDateTime.now();
      LocalDateTime tokyoDateTime = LocalDateTime.ofInstant(LocalDateTime.now().toInstant(ZoneOffset
      	.of("+08:00")),ZoneId.of("Asia/Tokyo"));
      	
     //假设本地为东京,获取大陆LocalDateTime
      LocalDateTime dateTime1 = LocalDateTime.now();
      LocalDateTime dateTime2 = LocalDateTime.ofInstant(dateTime1.toInstant(ZoneOffset.of("+09:00"))
      	,ZoneId.systemDefault());
      	
      ZoneId zoneId = ZoneId.of("Asia/Tokyo");
      ZonedDateTime zonedDateTime = ZonedDateTime.of(dateTime1, zoneId);
    
  • 运行结果:

    localDateTime*****  2019-12-24T13:31:32.277755700
    tokyoDateTime*****  2019-12-24T14:31:32.277755700
    
    2019-12-24T13:31:32.277755700
    2019-12-24T12:31:32.277755700
    
    Asia/Tokyo	
    2019-12-24T13:31:32.277755700+09:00[Asia/Tokyo]
    

示例二

  •   	//LocalDate(.atStartOfDay) + ZoneId -> ZoneDateTime
          ZoneId romeZone = ZoneId.of("Europe/Rome");
          LocalDate date = LocalDate.of(2014,3,18);
          ZonedDateTime zdt1 = date.atStartOfDay(romeZone);
    
          //LocalDateTime(.atZone) + ZoneId -> ZoneDateTime
          LocalDateTime dateTime = LocalDateTime.of(2014,3,18,13,45);
          ZonedDateTime zdt2 = dateTime.atZone(romeZone);
          
          //Instant(.atZone) + ZoneId -> ZoneDateTime
          Instant instant = Instant.now();
          ZonedDateTime zdt3 = instant.atZone(romeZone);
      	```
    
  • 运行结果
    2014-03-18T00:00+01:00[Europe/Rome]
    2014-03-18T13:45+01:00[Europe/Rome]
    本地instant2019-12-24T05:54:37.954459900Z
    2019-12-24T06:54:37.954459900+01:00[Europe/Rome]
    

示例三

  •   //注意一下
      zonedDateTime = ZonedDateTime.parse("2015-05-03T10:15:30+01:00[Europe/Paris]");		
      
      //然后,通过创建ZoneOffset并为localDateTime实例进行设置,将时间增加了两个小时:
      dateTime = LocalDateTime.now();
      ZoneOffset offset = ZoneOffset.of("+02:00");
      OffsetDateTime offSetByTwo = OffsetDateTime.of(dateTime, offset);
    
      LocalTime maxTime = LocalTime.MAX;
      
    
  • 运行结果

    2015-05-03T11:15:30+02:00[Europe/Paris]
    
    2019-12-24T12:07:44.748674600
    +02:00
    2019-12-24T12:07:44.748674600+02:00
    
    23:59:59.999999999
    

打印两地ZoneDateTime

  •   dateTime = LocalDateTime.now();
      zonedDateTime = dateTime.atZone(ZoneId.systemDefault());
      zonedDateTime = dateTime.atZone(ZoneId.of("Asia/Tokyo"));
    
      LocalDateTime 2019-12-24T11:19:22.717692200
      本地ZonedDateTime2019-12-24T11:19:22.717692200+08:00[Asia/Shanghai]
      东京ZonedDateTime2019-12-24T11:19:22.717692200+09:00[Asia/Tokyo]
    

补充知识

日期兼容问题
  •   
      //由Date和Calender转换为LocalDateTime
      LocalDateTime dateTime3 = LocalDateTime.ofInstant(new Date().toInstant(), ZoneId.systemDefault());
      LocalDateTime dateTime4 = LocalDateTime.ofInstant(new Calendar() {...}.toInstant(),ZoneId.systemDefault());
      //所述LocalDateTime可以从历元秒来构造如下。以下代码的结果将是LocalDateTime,表示2016-06-13T11:34:50:
      LocalDateTime dateTime5 = LocalDateTime.ofEpochSecond(1465817690, 0, ZoneOffset.UTC);
      
    
  • 运行结果

    2019-12-24T10:32:28.246
    1970-01-01T08:00   //canlender直接new不好,懒得学,想了解自己去看
    2016-06-13T11:34:50
    
所有ZoneId
  •   	Set<String> allZoneIds = ZoneId.getAvailableZoneIds();
          for(String str: allZoneIds) {
              System.out.println(str);
          }
    
  • 常用(主要是我认识的不多)

    Europe/London
    GMT
    CET
    Europe/Paris
    Asia/Hong_Kong
    Asia/Tokyo
    Asia/Shanghai
    Europe/Rome
    

杂乱区域

Local Date-Time 的简单使用

  •       public String Local() {
              //获取当前日期时间
              LocalDateTime currentTime = LocalDateTime.now();
              System.out.println("当前日期时间:"+currentTime);
              
              LocalDate date1 = currentTime.toLocalDate();
              System.out.println("当前日期:"+ date1);
      
              Month month = currentTime.getMonth();
              int day = currentTime.getDayOfMonth();
              int seconds = currentTime.getSecond();
              System.out.println("月: " + month +", 日: " + day +", 秒: " + seconds);
      
              //给定了日期与年份 date2:2012-12-10T16:10:38.992224100
              LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
              System.out.println("给定天数与年份:"+ date2);
      
              //给定日期 date3:2014-12-12
              LocalDate date3 = LocalDate.of(2014, Month.DECEMBER,12);
              System.out.println("由给定日期创建日期:"+ date3);
      
              //给定时间 date4:22:15
              LocalTime date4 = LocalTime.of(22,15);
              System.out.println("由给定时间创建时间:" + date4);
      
              //解析字符串 date5:20:15:30
              LocalTime date5 = LocalTime.parse("20:15:30");
              System.out.println("由给定时间创建时间:" + date5);
              
              return "1";
          }
    
  • 运行结果
    当前日期时间:2019-12-18T16:10:38.992224100
    当前日期:2019-12-18: DECEMBER,: 18,: 38
    给定天数与年份:2012-12-10T16:10:38.992224100
    由给定日期创建日期:2014-12-12
    由给定时间创建时间:22:15
    由给定时间创建时间:20:15:30
    

Zoned 的简单使用

  •  	public String Zoned() {
            //获取当前时间日期
            //date1:2012-12-12T13:05:10+08:00[Asia/Shanghai]
            ZonedDateTime date1 = ZonedDateTime.parse("2012-12-12T10:10:10+05:05[Asia/Shanghai]");
            System.out.println("date1:"+date1);
    
            //ZoneId:Europe/Paris  ???
            ZoneId id = ZoneId.of("Europe/Paris");
            System.out.println("ZoneId:"+ id);
    
            //Asia/Shanghai
            ZoneId currentZone = ZoneId.systemDefault();
            System.out.println(currentZone);
            return "2";
        }
    
  • 运行结果:

    date1:2012-12-12T13:05:10+08:00[Asia/Shanghai]
    ZoneId:Europe/Paris
    Asia/Shanghai
    

Chrono Units Enum

  • java.time.temporal.ChronoUnit枚举类用来用表示年、月、日等,这取代原来使用 int值来表示

    	public String ChronoUnit() {
            //Get the current date
            LocalDate today = LocalDate.now();
            System.out.println("Current date: " + today);
    
            //add 1 week to the current date
            LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
            System.out.println("Next week: " + nextWeek);
    
            //add 1 month to the current date
            LocalDate nextMonth = today.plus(1, ChronoUnit.MONTHS);
            System.out.println("Next month: " + nextMonth);
    
            //add 1 year to the current date
            LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
            System.out.println("Next year: " + nextYear);
    
            //add 10 years to the current date
            LocalDate nextDecade = today.plus(1, ChronoUnit.DECADES);
            System.out.println("Date after ten year: " + nextDecade);
            return null;
        }
    
  • 运行结果:

    Current date: 2019-12-18
    Next week: 2019-12-25
    Next month: 2020-01-18
    Next year: 2020-12-18
    Date after ten year: 2029-12-18
    

Period and Duration

Java 8 中两个类Period和Duration处理时间差:

  • Period - 处理日期差。

  • Duration - 处理时间差。

    public String pd() {
            /*****testPeriod*****/
            //Get the current date
            LocalDate date1 = LocalDate.now();
            System.out.println("Current date: " + date1);
    
            //add 1 month to the current date
            LocalDate date2 = date1.plus(1, ChronoUnit.MONTHS);
            System.out.println("Next month: " + date2);
    
            Period period = Period.between(date2, date1);
            System.out.println("Period: " + period);
    
            /*****testDuration*****/
            LocalTime time1 = LocalTime.now();
            Duration twoHours = Duration.ofHours(2);
    
            LocalTime time2 = time1.plus(twoHours);
            Duration duration = Duration.between(time1, time2);
    
            System.out.println("Duration: " + duration);
            return null;
        }
    
  • 运行结果:

    Current date: 2019-12-18
    Next month: 2020-01-18
    Period: P-1M
    Duration: PT2H
    

Backward Compatibility

  • toInstant()方法用来将老的Date对象转换为LocalDateTime或ZonedDateTime对象

    public String testBackwardCompatability() {
            //Get the current date
            Date currentDate = new Date();
            System.out.println("Current date: " + currentDate);
    
            //Get the instant of current date in terms of milliseconds
            Instant now = currentDate.toInstant();
            ZoneId currentZone = ZoneId.systemDefault();
    
            LocalDateTime localDateTime = LocalDateTime.ofInstant(now, currentZone);
            System.out.println("Local date: " + localDateTime);
    
            ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(now, currentZone);
            System.out.println("Zoned date: " + zonedDateTime);
            return null;
        }
    
  • 运行结果:

    Current date: Wed Dec 18 16:38:04 CST 2019
    Local date: 2019-12-18T16:38:04.741
    Zoned date: 2019-12-18T16:38:04.741+08:00[Asia/Shanghai]
    

参考文档:https://blog.csdn.net/weixin_37547589/article/details/90064465

  • LocalDateTime 为日期时间的计算提供了很大的方便, 在构造对象/运算/toString等方便都非常便利。

  • 3个常用的类:

    java.time.LocalDateTime;		推荐使用
    java.time.LocalDate;
    java.time.LocalTime;
    Instant
    Duration
    Period
    
发布了53 篇原创文章 · 获赞 13 · 访问量 2257

猜你喜欢

转载自blog.csdn.net/qq_36821220/article/details/103598823