当前位置:   article > 正文

快速学习Java8新特性第十讲——全新的日期时间API_java isodatetime

java isodatetime

或许这就是Java 8提供的全新日期时间API的由来吧?

Java 8提供了一套全新的日期时间API,为什么要这么干呢。因在旧版的Java中,日期时间API存在很多问题,比如说线程安全问题,java.util.Date是非线程安全的,所有的日期类都是可变的;又还有设计乱七八糟的问题,你去看看java.util.Date类会发现它的很多方法都被标记过时了,就知道SUN公司自己人都看不过去了;而且用于格式化和解析日期类的类在java.text包下,让人不禁想问是不是抽签随便分包的啊!还有使用起来不方便,就拿java.util.Calendar类来说,加几天和减几天都是用add方法,意义十分不明显。刚开始学的时候我是一脸懵逼,各种风中凌乱,从现在开始我就可以彻底地忘记它们了!!!因为Java 8来解救我了。

Java 8提供的这套日期时间API都在java.time包下,这个包涵盖了所有处理日期(date)、时间(time)、日期/时间(datetime)、时区(zone)、时间戳(instant)、间隔(duration)以及时钟(clock)的操作,可以说一包在手,天下我有。

当然了,在这里我不会一一介绍全部的类和方法,只是大概的用一下,只要记住一点,你想要的功能(别太偏门),别人都已经帮你实现了,不记得就去翻API文档吧!

日期、时间和日期时间

在这里插入图片描述
LocalDate、LocalTime以及LocalDateTime类的实例是不可变的对象,也就是说不管做什么样的改变,都将产生一个全新的实例,所以才说它是线程安全的,能够解决多线程的安全问题。它们分别表示使用ISO-8601日历系统的日期、时间以及日期和时间,它们提供了简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。温馨提示:ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法。

常用方法

这三个类的方法都差不多了多少,其常用方法有:
在这里插入图片描述
下面我就以LocalDateTime为例来演示一下上表所列出的一些方法。

@Test
public void test1() {
    LocalDateTime ldt = LocalDateTime.now();//获取当前系统日期时间
    System.out.println(ldt);
    
    LocalDateTime ldt2 = LocalDateTime.of(2017, 10, 19, 13, 22, 33);//构造一个指定日期时间(哪年哪月哪日  几时几分几秒)的对象
    System.out.println(ldt2);
    
    //注意,不管做什么样的改变,它都将产生一个全新的实例
    LocalDateTime ldt3 = ldt.plusYears(2);//将当前日期时间加上2年
    System.out.println(ldt3);
    
    LocalDateTime ldt4 = ldt.minusMonths(2);//将当前日期时间减去2个月
    System.out.println(ldt4);
    
    System.out.println(ldt.getYear());		  //输出当前日期时间的年份
    System.out.println(ldt.getMonthValue());  //输出当前日期时间的月份
    System.out.println(ldt.getDayOfMonth());  //输出当前日期时间的月份天数(即几号)
    System.out.println(ldt.getHour());        //输出当前日期时间的时
    System.out.println(ldt.getMinute());	  //输出当前日期时间的分
    System.out.println(ldt.getSecond());      //输出当前日期时间的秒
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

运行以上测试方法,你便能在Eclipse控制台中看到如下打印内容。
在这里插入图片描述

时间戳

时间戳对应的是java.time.Instant,它专门用于"时间戳"的运算。啥是"时间戳"啊?指的是从Unix元年(传统的设定为UTC时区1970年1月1日午夜时分)开始到某个时间之间的毫秒值。有一点需要知道,时间戳是给计算机读的,它不是给我们人读的。下面,我会用一个案例来演示一下时间戳。

@Test
public void test2() {
    Instant ins1 = Instant.now();//默认获取的是以UTC时区(世界协调时间,也叫格林威治时间)为基础的(当前时间的)时间戳
    System.out.println(ins1);//因为中国在东八区,所以这句代码输出的时间跟我的电脑时间是不同的
    
    //做一个偏移量的运算
    OffsetDateTime odt = ins1.atOffset(ZoneOffset.ofHours(8));//既然中国在东八区,故要偏移8个小时,这样子获取到的时间才是自己电脑的时间
    System.out.println(odt);//带偏移量的时间和日期
    
    System.out.println(ins1.toEpochMilli());//转成对应的毫秒值,如果是当前时间的时间戳,结果跟System.currentTimeMillis()是一样的
    
    //对时间戳做一个稍微的改变
    Instant ins2 = Instant.ofEpochSecond(60);
    System.out.println(ins2);//此时,得到的是1970-01-01T00:01:00Z,也即Unix元年过去1分钟之后的时间戳
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

运行以上测试方法,你便能在Eclipse控制台中看到如下打印内容。
在这里插入图片描述

间隔

表示间隔的有两个类,它们分别是:
在这里插入图片描述
使用Duration类不仅可以计算两个时间之间的间隔,还能计算两个时间戳之间的间隔。

@Test
public void test3() {
    Instant ins1 = Instant.now();
    try {
        Thread.sleep(3000);//中间睡一会
    } catch (InterruptedException e) {
        
    }
    Instant ins2 = Instant.now();
    
    //计算两个时间戳之间的间隔
    Duration duration = Duration.between(ins1, ins2);
    // System.out.println(duration);//PT3S
    System.out.println(duration.toMillis());//获取毫秒
    
    System.out.println("---------------------------------");
    
    LocalTime lt1 = LocalTime.now();
    try {
        Thread.sleep(3000);//中间睡一会
    } catch (InterruptedException e) {
        
    }
    LocalTime lt2 = LocalTime.now();
    
    //计算两个时间之间的间隔
    Duration duration2 = Duration.between(lt1, lt2);
    // System.out.println(duration2);//可能会输出PT3S或者输出PT3.001S,至于多出来的0.001秒其实就是除去线程睡眠时间之外执行计算时间间隔那句代码消耗的时间
    System.out.println(duration2.toMillis());//可能会输出3000或者输出3001
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

运行以上测试方法,你便能在Eclipse控制台中看到如下打印内容。
在这里插入图片描述
使用Period类可以计算两个日期之间的间隔,示例代码如下。

@Test
public void test4() {
    //起始时间指定为2019年1月1日
    LocalDate ld1 = LocalDate.of(2019, 1, 1);
    //终止时间指定为当前时刻
    LocalDate ld2 = LocalDate.now();
    
    Period period = Period.between(ld1, ld2);
    System.out.println(period);//可能会输出P11M17D,Y代表年,M代表月,D代表日,说明起始时间和当前时刻之间的日期间隔是0年11个月零17天
    
    System.out.println(period.getYears());
    System.out.println(period.getMonths());
    System.out.println(period.getDays());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

运行以上测试方法,你便能在Eclipse控制台中看到如下打印内容。
在这里插入图片描述

时间校正器

有时我们可能需要执行一些特殊的操作,例如将日期调整到"下一个周日"、"下一个工作日"或者"下一个结婚纪念日"等操作。执行这些特殊的操作,就得使用到TemporalAdjuster,它是一个接口,也被称为时间校正器。除此之外,还得知道一个TemporalAdjusters类,该类通过静态方法提供了大量的常用TemporalAdjuster的实现。

如果要想将日期调整到"下一个周日",那么该咋办呢?

@Test
public void test5() {
    LocalDateTime ldt = LocalDateTime.now();
    System.out.println(ldt);
    
    LocalDateTime ldt2 = ldt.withDayOfMonth(10);//将当前系统日期时间中的月份天数指定为10
    System.out.println(ldt2);
    
    //通过时间校正器,就可以指定一些特殊的操作了,比如说下一个周日、下一个工作日、下一个结婚纪念日
    //下一个周日
    LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
    System.out.println(ldt3);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

运行以上测试方法,你便能在Eclipse控制台中看到如下打印内容。
在这里插入图片描述
现在,我们想要将日期调整到"下一个工作日",那么又该咋办呢?

@Test
public void test5() {
    LocalDateTime ldt = LocalDateTime.now();
    System.out.println(ldt);
    
    //通过时间校正器,就可以指定一些特殊的操作了,比如说下一个周日、下一个工作日、下一个结婚纪念日
    //自定义:下一个工作日
    LocalDateTime ldt5 = ldt.with((l) -> {
        LocalDateTime ldt4 = (LocalDateTime)l;
        //获取周几?即这一天到底是周几?
        DayOfWeek dow = ldt4.getDayOfWeek();
        //如果是周五的话,那么就加3天
        if (dow.equals(DayOfWeek.FRIDAY)) {
            return ldt4.plusDays(3);
        } else if (dow.equals(DayOfWeek.SATURDAY)) {
            return ldt4.plusDays(2);
        } else {
            return ldt4.plusDays(1);
        }
    });
    System.out.println(ldt5);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

运行以上测试方法,你便能在Eclipse控制台中看到如下打印内容。
在这里插入图片描述

解析与格式化

以前我们用的日期时间格式化的类是java.text.SimpleDateFormat,而Java 8提供的日期时间格式化类是java.time.format.DateTimeFormatter,该类提供了三种格式化方法:

  1. 预定义的标准格式;
  2. 语言环境相关的格式;
  3. 自定义的格式。

下面,我会用一个案例来演示一下如何解析与格式化日期/时间。

@Test
public void test6() {
    // DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;//DateTimeFormatter类提供了很多种预定义的标准格式
    DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE;//这里使用了ISO_DATE这种格式
    LocalDateTime ldt = LocalDateTime.now();//获取当前系统日期时间

    String strDate = ldt.format(dtf);//指定格式化器格式日期时间
    System.out.println(strDate);
    
    System.out.println("----------------------------------");
    
    //使用自定义的格式
    DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    String strDate2 = dtf2.format(ldt);
    System.out.println(strDate2);
    
    //字符串解析回日期
    LocalDateTime newDate = ldt.parse(strDate2, dtf2);
    System.out.println(newDate);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

运行以上测试方法,你便能在Eclipse控制台中看到如下打印内容。
在这里插入图片描述

时区

Java 8中加入了对时区的支持,带时区的时间为分别为:ZonedDate、ZonedTime以及ZonedDateTime。其中每个时区都对应着地区ID,地区ID都为"{区域}/{城市}"的格式,例如Asia/Shanghai。

还有一个类,我们也得知道,用的还比较多,它就是ZoneId,该类包含了所有的时区信息,而且它还有两个比较常用的方法,它们分别是:
在这里插入图片描述
我们可以通过java.time.ZoneId类去查看在Java 8中支持的时区有哪些,如:

@Test
public void test7() {
    //在Java 8中,支持多少时区
    Set<String> set = ZoneId.getAvailableZoneIds();
    set.forEach(System.out::println);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

运行以上测试方法,你便能在Eclipse控制台中看到在Java 8中所支持的时区了。
在这里插入图片描述
我们可以对时区进行如下操作:

@Test
public void test8() {
    LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));//指定一个时区去构建一个日期时间
    System.out.println(ldt);
                                            //指定一个时区
    LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
    ZonedDateTime zdt = ldt2.atZone(ZoneId.of("Asia/Shanghai"));//构建出一个带时区的时间和日期
    System.out.println(zdt);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

运行以上测试方法,你便能在Eclipse控制台中看到如下打印内容。
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/372222
推荐阅读
相关标签
  

闽ICP备14008679号